隨筆 - 303  文章 - 883  trackbacks - 0
          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          歡迎光臨! 
          閑聊 QQ:1074961813

          隨筆分類(357)

          我管理的群

          公共blog

          • n維空間
          • Email : java3d@126.com 群 : 12999758

          參與管理的論壇

          好友的blog

          我的其他blog

          朋友的網站

          搜索

          •  

          最新評論

           做新男人

          年紀大的人通常會有一種感覺(實際上我還不算大),那就是年輕一代和自己的思想往往會有一些出入,小弟在這里發表下個人拙見,如有看完不爽者請諒解:現在網上年輕一代不是正流行非主流文化嘛!對于一些老人家,往往喜歡對這些現象品頭論足,說起來這時代發展就這樣唄,想想我們當年,嘿嘿,就我而言吧!徹底的保守派,在很多年輕人看來,從思想或行動上看,完全是個古董那種。但俺也有自己的苦衷,一方面父母管得嚴,一方面自己生活的環境接觸的人就這樣,有什么辦法呢?于是我選擇認命,幸運的是到目前為止,活得還算瀟灑,嘿嘿(有點自戀了)。但啊,這時代究竟是時代啊!某一天又出來個新主流了,有人出生的地方,再新的思想就總會有過時的時候。中國有句話說得響亮:“與時俱進”,個人覺得挺有道理,社會生產力發展著,人的需求也在發生變化,哪個時候,沒學會玩電腦就算文盲,是吧?這個女人啊!也一樣,需求也是越來越豐富啊!市場經濟,有需求就會有提供,做新男人,也成了一種新時尚。話是這么說,但不管如何始終還是個男人,這點還沒變。

          據說在Linux 2.6.18版本的內核之后,出現了一種新的管理設備文件的方法,叫udevuserspace device management)取代我們之前看到的那種devfs管理方式。(這個我也是今天晚上有人告訴,我才知道的,悲哀的很,要知道孤陋寡聞的人是很容易被淘汰的~~怕怕,于是上官網look了下,搞了這個文章算是知識補充吧!),udev的官方文檔對它做了如下定義:udev是一種用戶空間上的應用程序,它動態地為位于/dev下的當前正被使用的設備,提供一個唯一的入口,udev將取代devfs。關于udev的優勢,網上大把資料,試問,哪個東西出來的時候沒吹上一車呢,自己seesee,不說也罷!

              下面是一個是一個完整的usb驅動,有人要問了,你小子怎么老來usb,換個其他的,可以不?嘿嘿,對usb太情有獨鐘了,一想到驅動,總是到它。

          與前面所說的devfs在使用上是有所區別的,結構體、使用的函數和實現步驟都存在差異,所謂差異就是說它們還是有一些相似之處的,新男人也還是男人這點還沒變。在\linux-2.6.16.20\include\linux\device.h中做如下定義:

          struct class {

              const char    * name;

              struct module     * owner;

           

              struct subsystem  subsys;

              struct list_head  children;

              struct list_head  interfaces;

              struct semaphore  sem;   /* locks both the children and interfaces lists */

           

              struct class_attribute      * class_attrs;

              struct class_device_attribute   * class_dev_attrs;

           

              int (*uevent)(struct class_device *dev, char **envp,

                        int num_envp, char *buffer, int buffer_size);

           

              void   (*release)(struct class_device *dev);

              void   (*class_release)(struct class *class);

          };

           

          struct class_device {

              struct list_head  node;

           

              struct kobject       kobj;

              struct class      * class;   /* required */

              dev_t         devt;      /* dev_t, creates the sysfs "dev" */

              struct class_device_attribute *devt_attr;

              struct class_device_attribute uevent_attr;

              struct device     * dev;     /* not necessary, but nice to have */

              void          * class_data; /* class-specific data */

              struct class_device  *parent;   /* parent of this child device, if there is one */

           

              void   (*release)(struct class_device *dev);

              int (*uevent)(struct class_device *dev, char **envp,

                        int num_envp, char *buffer, int buffer_size);

              char   class_id[BUS_ID_SIZE];   /* unique to this class */

          };

          對特定的設備使用特定的結構,下面兩個結構來自\linux-2.6.16.20\include\linux\usb.h

          struct usb_interface {

              /* array of alternate settings for this interface,

               * stored in no particular order */

              struct usb_host_interface *altsetting;

           

              struct usb_host_interface *cur_altsetting;    /* the currently

                             * active alternate setting */

              unsigned num_altsetting; /* number of alternate settings */

           

              int minor;        /* minor number this interface is

                             * bound to */

              enum usb_interface_condition condition;       /* state of binding */

              struct device dev;       /* interface specific device info */

              struct class_device *class_dev;

          };

           

          struct usb_class_driver {

              char *name;

              struct file_operations *fops;

              int minor_base;

          };

           

          在創建的時候要使用到以下函數,它們在\linux-2.6.16.20\include\linux\device.h中定義如下:

          extern struct class *class_create(struct module *owner, char *name);//創建一個類,返回一個class

          extern void class_destroy(struct class *cls);//銷毀一個類

          extern struct class_device *class_device_create(struct class *cls,

                               struct class_device *parent,

                               dev_t devt,

                               struct device *device,

                               char *fmt, ...)

                            __attribute__((format(printf,5,6)));//為類創建一個類設備,返回一個class_device

          extern void class_device_destroy(struct class *cls, dev_t devt);//銷毀一個類設備

           

          使用過程可以是這樣的(注意:這里做了省略處理):

          static struct class *usb_class;

           

          int usb_major_init(void)

          {

              usb_class = class_create(THIS_MODULE, "usb");

          }

           

          void usb_major_cleanup(void)

          {

              class_destroy(usb_class);

          }

           

          int usb_register_dev(struct usb_interface *intf,//class_device為參

                      struct usb_class_driver *class_driver)

          {

              intf->class_dev = class_device_create(usb_class, NULL,

                                MKDEV(USB_MAJOR, minor), //以主設備號和次設備號為參

                                 &intf->dev, "%s", temp);

          }

           

          EXPORT_SYMBOL(usb_register_dev);

           

          void usb_deregister_dev(struct usb_interface *intf,

                     struct usb_class_driver *class_driver)

          {

             class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));

          }

           

          EXPORT_SYMBOL(usb_deregister_dev);

           

          于是對于udev我們又可以得到一個省口水的圖:

           

          Udev設備管理方式

          Devfs設備管理方式

          包含必要的頭文件

          包含必要的頭文件

          填充file_operations

          填充file_operations

          創建usb_class

          填充usb_driver

          register\deregister
          +

          class_device_create\ class_device_destroy

          usb_register\usb_deregister

          EXPORT_SYMBOL

          module_init\ module_exit


          下面給出一個完整的代碼

          來自:\linux-2.6.16.20\drivers\usb\core\file.c

          #include <linux/config.h>

          #include <linux/module.h>

          #include <linux/spinlock.h>

          #include <linux/errno.h>

          #include <linux/usb.h>

           

          #include "usb.h"

           

          #define MAX_USB_MINORS   256

          static struct file_operations *usb_minors[MAX_USB_MINORS];

          static DEFINE_SPINLOCK(minor_lock);

           

          static int usb_open(struct inode * inode, struct file * file)

          {

              int minor = iminor(inode);

              struct file_operations *c;

              int err = -ENODEV;

              struct file_operations *old_fops, *new_fops = NULL;

           

              spin_lock (&minor_lock);

              c = usb_minors[minor];

           

              if (!c || !(new_fops = fops_get(c))) {

                 spin_unlock(&minor_lock);

                 return err;

              }

              spin_unlock(&minor_lock);

           

              old_fops = file->f_op;

              file->f_op = new_fops;

              /* Curiouser and curiouser... NULL ->open() as "no device" ? */

              if (file->f_op->open)

                 err = file->f_op->open(inode,file);

              if (err) {

                 fops_put(file->f_op);

                 file->f_op = fops_get(old_fops);

              }

              fops_put(old_fops);

              return err;

          }

           

          static struct file_operations usb_fops = {

              .owner =   THIS_MODULE,

              .open =       usb_open,

          };

           

          static struct class *usb_class;

           

          int usb_major_init(void)

          {

              int error;

           

              error = register_chrdev(USB_MAJOR, "usb", &usb_fops);

              if (error) {

                 err("unable to get major %d for usb devices", USB_MAJOR);

                 goto out;

              }

           

              usb_class = class_create(THIS_MODULE, "usb");

              if (IS_ERR(usb_class)) {

                 error = PTR_ERR(usb_class);

                 err("class_create failed for usb devices");

                 unregister_chrdev(USB_MAJOR, "usb");

                 goto out;

              }

           

          out:

              return error;

          }

           

          void usb_major_cleanup(void)

          {

              class_destroy(usb_class);

              unregister_chrdev(USB_MAJOR, "usb");

          }

           

          int usb_register_dev(struct usb_interface *intf,

                      struct usb_class_driver *class_driver)

          {

              int retval = -EINVAL;

              int minor_base = class_driver->minor_base;

              int minor = 0;

              char name[BUS_ID_SIZE];

              char *temp;

           

          #ifdef CONFIG_USB_DYNAMIC_MINORS

              minor_base = 0;

          #endif

              intf->minor = -1;

           

              dbg ("looking for a minor, starting at %d", minor_base);

           

              if (class_driver->fops == NULL)

                 goto exit;

           

              spin_lock (&minor_lock);

              for (minor = minor_base; minor < MAX_USB_MINORS; ++minor) {

                 if (usb_minors[minor])

                     continue;

           

                 usb_minors[minor] = class_driver->fops;

           

                 retval = 0;

                 break;

              }

              spin_unlock (&minor_lock);

           

              if (retval)

                 goto exit;

           

              intf->minor = minor;

           

              /* create a usb class device for this usb interface */

              snprintf(name, BUS_ID_SIZE, class_driver->name, minor - minor_base);

              temp = strrchr(name, '/');

              if (temp && (temp[1] != 0x00))

                 ++temp;

              else

                 temp = name;

             intf->class_dev = class_device_create(usb_class, NULL,

                                MKDEV(USB_MAJOR, minor),

                                &intf->dev, "%s", temp);

              if (IS_ERR(intf->class_dev)) {

                 spin_lock (&minor_lock);

                 usb_minors[intf->minor] = NULL;

                 spin_unlock (&minor_lock);

                 retval = PTR_ERR(intf->class_dev);

              }

          exit:

              return retval;

          }

          EXPORT_SYMBOL(usb_register_dev);

           

          void usb_deregister_dev(struct usb_interface *intf,

                     struct usb_class_driver *class_driver)

          {

              int minor_base = class_driver->minor_base;

              char name[BUS_ID_SIZE];

           

          #ifdef CONFIG_USB_DYNAMIC_MINORS

              minor_base = 0;

          #endif

           

              if (intf->minor == -1)

                 return;

           

              dbg ("removing %d minor", intf->minor);

           

              spin_lock (&minor_lock);

              usb_minors[intf->minor] = NULL;

              spin_unlock (&minor_lock);

           

              snprintf(name, BUS_ID_SIZE, class_driver->name, intf->minor - minor_base);

              class_device_destroy(usb_class, MKDEV(USB_MAJOR, intf->minor));

              intf->class_dev = NULL;

              intf->minor = -1;

          }

          EXPORT_SYMBOL(usb_deregister_dev);


              從這篇文我們發現,技術是不斷變化的,換句話說,女人是善變的感情動物,請不要誤會,是感情動物:意為善于使用感情作為武器;而絕不是多情,多情是用來形容男人的嘛!對不?呵呵,胡說八道了吧~~
              到這里我們還沒說這些要怎么安裝配置呢,下個文章見吧!



          地震讓大伙知道:居安思危,才是生存之道。
          posted on 2008-05-03 09:24 小尋 閱讀(5187) 評論(4)  編輯  收藏 所屬分類: kernel

          FeedBack:
          # re: 如何編寫Linux 驅動程序(四) 2008-05-15 11:44 暈翻
          看完你寫的"驅動沒什么新鮮玩意兒",我在想,LDD那本書居然還在出版,讓我非常疑惑.僅僅填幾個結構就是驅動程序了啊....怎么連寫個積存器的動作都沒....  回復  更多評論
            
          # re: 如何編寫Linux 驅動程序(四) 2008-05-15 17:50 幻想~@@~
                  寄存器是有的吧! 感覺寫驅動就是做填充動作,并發、I/O控制大多由OS內核完成,聽高手說寫驅動就是內核API 嘿嘿!
                 你剛剛所說的是底層驅動是接近于裸跑的那種吧~~~ 這部分是系統剛啟動的時候,硬件初始化階段完成的,之后這些就交給OS管理了,PC機上這部分內容一部分被包含在BIOS里,一部分包含在OS里。
                  比如,在linux 2.6.×源代碼中每種體系結構的CPU“arch\(CPU類型)\boot”都有這部分的啟動代碼,其原理與0.11差不多,不同在于o.11支持的CPU只有X86,所以,boot代碼只有"/boot"下,對X86平臺而言,這部分的代碼對CPU的寄存器,內存(中斷、分頁),i/o做了簡單的初始化,接著系統做了實虛模式轉換,硬件資源交與OS內核管理,所以在這種情況下,一切都驅動都是通過注冊到內核來實現的,當你填充這些數據結構時,系統會在必要時調用,用戶這個時候通過file_operation結構實現,以文件方式管理硬件設備。當然有時候,我們需要在驅動中加入自己的數據結構并對硬件(寄存器等)做初始化。
                 如果你對這些內容感興趣,可以找u-boot或vivi 等bootloader看看,在嵌入平臺這部分被分開了,它們不但負責硬件初始化,還負責內核下載,調試等功能。事實上,上面給的驅動是不完全的,非典型的,只是一個簡單的介紹,如果要做詳細道底層的介紹,我還需要一段時間做準備,寫得太離譜的話對初學者來說,是致命的,還有我感覺ldd寫得相當不錯,可能我比較SB吧,似乎每句話都蘊含深刻的含義!為確保無誤的理解,讀得很慢。下來我會對如何安裝這些驅動和一些細節的東西做盡量詳細介紹~~~ 最近比較多事情,所以沒趕上
            回復  更多評論
            
          # re: 如何編寫Linux 驅動程序(四) 2008-10-29 10:15 liwensir
          我編譯《linux高級程序設計》第9章中的“plp_kmen.c”示例模塊時,提示有如下錯誤,書中是基于2.6.15,我內核樹版本為2.6.27,
          ...
          在函數 ‘plp_kmem_init’ 中:
          /home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:193: 錯誤:隱式聲明函數 ‘class_device_create’
          /home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:
          在函數 ‘plp_kmem_exit’ 中:
          /home/lwxiao/mymodule/9_plp_kmem/plp_kmem.c:212: 錯誤:隱式聲明函數 ‘class_device_destroy’
          ...

          我查過 device.h 頭文件,從2.6.15到2.6.27,這兩個函數已經改過了,
          class_device_create 這個函數在2.6.27的device.h頭中已經沒有了,不知道替換函數是哪個
          class_device_destroy 這個函數還在,但參數已經變了

          由于本人水平太菜,實在不知道如何修改示例,讓其能成功編譯,
          哪位能提示下,不甚感激  回復  更多評論
            
          # re: 如何編寫Linux 驅動程序(四) 2008-10-29 22:34 小尋
          根據你所提供的信息,我在2.6.27內核里找到與class_device_create和class_device_destroy對應的兩句代碼。
           intf->usb_dev = device_create_drvdata(usb_class->class&intf->dev,
                     MKDEV(USB_MAJOR, minor), NULL,
                     
          "%s", temp);

          device_destroy(usb_class
          ->class, MKDEV(USB_MAJOR, intf->minor));
          不知能否幫助你解決目前遇到的問題?
            回復  更多評論
            
          主站蜘蛛池模板: 基隆市| 鄂伦春自治旗| 修武县| 阿鲁科尔沁旗| 改则县| 岳阳市| 鄂尔多斯市| 玉门市| 佛山市| 卢龙县| 阿拉善右旗| 贵阳市| 子长县| 高清| 航空| 阳谷县| 西林县| 兴宁市| 东城区| 客服| 蒙山县| 苍溪县| 婺源县| 佛学| 万源市| 白山市| 通州区| 中江县| 福安市| 密云县| 梓潼县| 邢台县| 光山县| 香河县| 资溪县| 永福县| 乌什县| 灌云县| 辉县市| 蒙山县| 海盐县|