<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

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

    歡迎光臨! 
    閑聊 QQ:1074961813

    隨筆分類(357)

    我管理的群

    公共blog

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

    參與管理的論壇

    好友的blog

    我的其他blog

    朋友的網(wǎng)站

    搜索

    •  

    最新評論

     做新男人

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

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

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

    與前面所說的devfs在使用上是有所區(qū)別的,結(jié)構(gòu)體、使用的函數(shù)和實現(xiàn)步驟都存在差異,所謂差異就是說它們還是有一些相似之處的,新男人也還是男人這點還沒變。在\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 */

    };

    對特定的設(shè)備使用特定的結(jié)構(gòu),下面兩個結(jié)構(gòu)來自\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;

    };

     

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

    extern struct class *class_create(struct module *owner, char *name);//創(chuàng)建一個類,返回一個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)));//為類創(chuàng)建一個類設(shè)備,返回一個class_device

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

     

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

    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), //以主設(shè)備號和次設(shè)備號為參

                           &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設(shè)備管理方式

    Devfs設(shè)備管理方式

    包含必要的頭文件

    包含必要的頭文件

    填充file_operations

    填充file_operations

    創(chuàng)建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);


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



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

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

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

    由于本人水平太菜,實在不知道如何修改示例,讓其能成功編譯,
    哪位能提示下,不甚感激  回復(fù)  更多評論
      
    # re: 如何編寫Linux 驅(qū)動程序(四) 2008-10-29 22:34 小尋
    根據(jù)你所提供的信息,我在2.6.27內(nèi)核里找到與class_device_create和class_device_destroy對應(yīng)的兩句代碼。
     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));
    不知能否幫助你解決目前遇到的問題?
      回復(fù)  更多評論
      
    主站蜘蛛池模板: 亚洲神级电影国语版| 国产成人精品久久亚洲高清不卡| 国产黄色片在线免费观看| 亚洲男人在线无码视频| 久久久久亚洲av无码专区蜜芽| 亚洲日本一区二区三区在线| 亚洲国产日韩在线一区| 色多多www视频在线观看免费| 美女露100%胸无遮挡免费观看| 老司机免费午夜精品视频| 蜜桃视频在线观看免费视频网站WWW| 免费人妻无码不卡中文字幕系| 99视频精品全部免费观看| 免费国产a国产片高清网站| 亚洲精品中文字幕乱码| 一级毛片免费不卡| 成人无码区免费视频观看| 亚洲欧洲美洲无码精品VA| 亚洲精品无码专区| 免费福利电影在线观看| 免费人成激情视频| 亚洲国产视频网站| a毛片视频免费观看影院| 日韩免费视频播播| 亚洲成a人片在线观看中文!!!| 亚洲一区二区观看播放| 免费av片在线观看网站| 亚洲国产精品碰碰| 亚洲国产午夜精品理论片在线播放| 免费一区二区三区在线视频| 午夜性色一区二区三区免费不卡视频| 成人性生交大片免费看午夜a| 日韩伦理片电影在线免费观看| 亚洲av无码天堂一区二区三区 | 亚洲综合在线观看视频| 日韩色视频一区二区三区亚洲| 免费VA在线观看无码| 韩国免费一级成人毛片| 久久综合亚洲色HEZYO社区| 久久国产精品免费一区二区三区| 13一14周岁毛片免费|