<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)站

    搜索

    •  

    最新評論

     做新男人

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

    據(jù)說在Linux 2.6.18版本的內(nèi)核之后,出現(xiàn)了一種新的管理設(shè)備文件的方法,叫udevuserspace device management)取代我們之前看到的那種devfs管理方式。(這個我也是今天晚上有人告訴,我才知道的,悲哀的很,要知道孤陋寡聞的人是很容易被淘汰的~~怕怕,于是上官網(wǎng)look了下,搞了這個文章算是知識補充吧?。?,udev的官方文檔對它做了如下定義:udev是一種用戶空間上的應(yīng)用程序,它動態(tài)地為位于/dev下的當前正被使用的設(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 小尋 閱讀(5183) 評論(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)的,當你填充這些數(shù)據(jù)結(jié)構(gòu)時,系統(tǒng)會在必要時調(diào)用,用戶這個時候通過file_operation結(jié)構(gòu)實現(xiàn),以文件方式管理硬件設(shè)備。當然有時候,我們需要在驅(qū)動中加入自己的數(shù)據(jù)結(jié)構(gòu)并對硬件(寄存器等)做初始化。
           如果你對這些內(nèi)容感興趣,可以找u-boot或vivi 等bootloader看看,在嵌入平臺這部分被分開了,它們不但負責硬件初始化,還負責內(nèi)核下載,調(diào)試等功能。事實上,上面給的驅(qū)動是不完全的,非典型的,只是一個簡單的介紹,如果要做詳細道底層的介紹,我還需要一段時間做準備,寫得太離譜的話對初學者來說,是致命的,還有我感覺ldd寫得相當不錯,可能我比較SB吧,似乎每句話都蘊含深刻的含義!為確保無誤的理解,讀得很慢。下來我會對如何安裝這些驅(qū)動和一些細節(jié)的東西做盡量詳細介紹~~~ 最近比較多事情,所以沒趕上
      回復(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ù)  更多評論
      
    主站蜘蛛池模板: 成年女人18级毛片毛片免费观看| 亚洲国产成人综合| 成人看的午夜免费毛片| 久久精品国产大片免费观看| 曰韩无码AV片免费播放不卡 | 久久精品免费大片国产大片| 亚洲国产欧美一区二区三区| 中文字幕亚洲色图| 亚洲国产精品特色大片观看完整版 | 国产三级免费电影| 女人18毛片a级毛片免费视频| 色欲国产麻豆一精品一AV一免费 | 99re6免费视频| 国内精品免费在线观看| 亚洲视频在线免费| 青青青视频免费观看| 立即播放免费毛片一级| 亚洲av乱码一区二区三区按摩| 亚洲综合偷自成人网第页色| 亚洲人成网站在线观看播放动漫| 亚洲天堂男人天堂| 亚洲精品免费观看| 久久精品国产精品亚洲艾| 国产精品亚洲аv无码播放| 激情综合色五月丁香六月亚洲| 亚洲美日韩Av中文字幕无码久久久妻妇| 国产精品自在自线免费观看| 免费看大美女大黄大色| 天天看免费高清影视| 69成人免费视频无码专区| 噼里啪啦电影在线观看免费高清| 亚洲免费视频观看| 午夜性色一区二区三区免费不卡视频| 最近中文字幕免费完整 | 国产亚洲中文日本不卡二区 | 大地资源在线观看免费高清| 免费不卡视频一卡二卡| 毛片a级毛片免费观看品善网 | 国产精品亚洲综合久久| 亚洲欧美日韩综合久久久| 亚洲av成人片在线观看|