日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

使用cdev_add注册字符设备

發(fā)布時(shí)間:2024/9/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用cdev_add注册字符设备 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在前面已經(jīng)提到設(shè)備號(hào)有主設(shè)備號(hào)和次設(shè)備號(hào),其中主設(shè)備號(hào)表示設(shè)備類?型,對(duì)應(yīng)于確定的驅(qū)動(dòng)程序,具備相同主設(shè)備號(hào)的設(shè)備之間共用同一個(gè)驅(qū)動(dòng)程?序,而用次設(shè)備號(hào)來(lái)標(biāo)識(shí)具體物理設(shè)備。因此在創(chuàng)建字符設(shè)備之前,必須先獲?得設(shè)備的編號(hào)(可能需要分配多個(gè)設(shè)備號(hào))。

在?Linux?2.6?的版本中,用?dev_t?類型來(lái)描述設(shè)備號(hào)(dev_t?是?32?位數(shù)值類型,其?中高?12?位表示主設(shè)備號(hào),低?20?位表示次設(shè)備號(hào))。用兩個(gè)宏?MAJOR?和?MINOR?分別?獲得?dev_t?設(shè)備號(hào)的主設(shè)備號(hào)和次設(shè)備號(hào),而且用?MKDEV?宏來(lái)實(shí)現(xiàn)逆過(guò)程,即組合?主設(shè)備號(hào)和次設(shè)備號(hào)而獲得?dev_t?類型設(shè)備號(hào)。

分配設(shè)備號(hào)有靜態(tài)和動(dòng)態(tài)的兩種方法。靜態(tài)分配(register_chrdev_region()函數(shù))是?指在事先知道設(shè)備主設(shè)備號(hào)的情況下,通過(guò)參數(shù)函數(shù)指定第一個(gè)設(shè)備號(hào)(它的次設(shè)備?號(hào)通常為?0)而向系統(tǒng)申請(qǐng)分配一定數(shù)目的設(shè)備號(hào)。動(dòng)態(tài)分配(alloc_chrdev_region())?是指通過(guò)參數(shù)僅設(shè)置第一個(gè)次設(shè)備號(hào)(通常為?0,事先不會(huì)知道主設(shè)備號(hào))和要分配?的設(shè)備數(shù)目而系統(tǒng)動(dòng)態(tài)分配所需的設(shè)備號(hào)。通過(guò)?unregister_chrdev_region()函數(shù)釋放已分配的(無(wú)論是靜態(tài)的還是動(dòng)態(tài)的)設(shè)?備號(hào)。

在Linux 2.6內(nèi)核中的字符設(shè)備用cdev結(jié)構(gòu)來(lái)描述,其定義如下:

struct?cdev? ? { ? ????struct?kobject?kobj; ? ????struct?module?*owner;?//所屬模塊 ? ????const?struct?file_operations?*ops;?//文件操作結(jié)構(gòu) ? ????struct?list_head?list; ? ????dev_t?dev;?//設(shè)備號(hào),int?類型,高12位為主設(shè)備號(hào),低20位為次設(shè)備號(hào) ? ????unsigned?int?count; ? }; ?

下面一組函數(shù)用來(lái)對(duì)cdev結(jié)構(gòu)進(jìn)行操作: struct?cdev?*cdev_alloc(void);//分配一個(gè)cdev ? void?cdev_init(struct?cdev?*,?const?struct?file_operations?*);//初始化cdev的file_operation ? void?cdev_put(struct?cdev?*p);//?//減少使用計(jì)數(shù) ? //注冊(cè)設(shè)備,通常發(fā)生在驅(qū)動(dòng)模塊的加載函數(shù)中 ? int?cdev_add(struct?cdev?*,?dev_t,?unsigned);? ? //注銷設(shè)備,通常發(fā)生在驅(qū)動(dòng)模塊的卸載函數(shù)中 ? void?cdev_del(struct?cdev?*);??

使用cdev_add注冊(cè)字符設(shè)備前應(yīng)該先調(diào)用register_chrdev_region或alloc_chrdev_region分配設(shè)備號(hào)。register_chrdev_region函數(shù)用于指定設(shè)備號(hào)的情況,alloc_chrdev_region函數(shù)用于動(dòng)態(tài)申請(qǐng)?jiān)O(shè)備號(hào),系統(tǒng)自動(dòng)返回沒(méi)有占用的設(shè)備號(hào)。

int?register_chrdev_region(dev_t?from,?unsigned?count,?const?char?*name)?; ? int?alloc_chrdev_region(dev_t?*dev,unsigned?baseminor,unsigned?count,const?char?*name);?

函數(shù)傳入值

first:要分配的設(shè)備號(hào)的初始值

?count:要分配(釋放)的設(shè)備號(hào)數(shù)目

?name:要申請(qǐng)?jiān)O(shè)備號(hào)的設(shè)備名稱(在/proc/devices?和?sysfs?中顯示)?

dev:動(dòng)態(tài)分配的第一個(gè)設(shè)備號(hào)

函數(shù)返回值

??????????????? 成功:0(只限于兩種注冊(cè)函數(shù))

??????????????? 出錯(cuò):?1(只限于兩種注冊(cè)函數(shù))

alloc_chrdev_region申請(qǐng)一個(gè)動(dòng)態(tài)主設(shè)備號(hào),并申請(qǐng)一系列次設(shè)備號(hào)。baseminor為起始次設(shè)備號(hào),count為次設(shè)備號(hào)的數(shù)量。注銷設(shè)備號(hào)(cdev_del)后使用unregister_chrdev_region:
  • void?unregister_chrdev_region(dev_t?from,unsigned?count)?;?
  • 這里講解?2.6?內(nèi)核中的字符設(shè)備的注冊(cè)和注銷過(guò)程。

    在?Linux?內(nèi)核中使用?struct?cdev?結(jié)構(gòu)來(lái)描述字符設(shè)備,我們?cè)隍?qū)動(dòng)程序中必?須將已分配到的設(shè)備號(hào)以及設(shè)備操作接口(即為?struct?file_operations?結(jié)構(gòu))賦予?struct?cdev?結(jié)構(gòu)變量。首先使用?cdev_alloc()函數(shù)向系統(tǒng)申請(qǐng)分配?struct?cdev?結(jié)構(gòu),?再用?cdev_init()函數(shù)初始化已分配到的結(jié)構(gòu)并與?file_operations?結(jié)構(gòu)關(guān)聯(lián)起來(lái)。最?后調(diào)用?cdev_add()函數(shù)將設(shè)備號(hào)與?struct??cdev?結(jié)構(gòu)進(jìn)行關(guān)聯(lián)并向內(nèi)核正式報(bào)告新?設(shè)備的注冊(cè),這樣新設(shè)備可以被用起來(lái)了。

    如果要從系統(tǒng)中刪除一個(gè)設(shè)備,則要調(diào)用?cdev_del()函數(shù)。

    例1.4? cdev_add注冊(cè)字符設(shè)備實(shí)例

    代碼見(jiàn)光盤\src\1drivermodel\1-4cdev。核心代碼如下所示:

  • struct?file_operations?simple_fops?=?{ ?
  • ????.owner?=????THIS_MODULE, ?
  • ????.read?=?????simple_read, ?
  • ????.write?=????simple_write, ?
  • ????.open?=?????simple_open, ?
  • ????.release?=??simple_release, ?
  • }; ?
  • /******************************************************* ?
  • ????????????????MODULE?ROUTINE ?
  • *******************************************************/ ?
  • void?simple_cleanup_module(void) ?
  • { ?
  • ????dev_t?devno?=?MKDEV(simple_MAJOR,?simple_MINOR); ?
  • ????if?(simple_devices)? ?
  • ????{ ?
  • ????????cdev_del(&simple_devices->cdev); ?
  • ????????kfree(simple_devices); ?
  • ????} ?
  • ????unregister_chrdev_region(devno,1); ?
  • } ?
  • //模塊初始化 ?
  • int?simple_init_module(void) ?
  • { ?
  • ????int?result; ?
  • ????dev_t?dev?=?0; ?
  • ????dev?=?MKDEV(simple_MAJOR,?simple_MINOR); ?
  • ????result?=?register_chrdev_region(dev,?1,?"DEMO");//申請(qǐng)?jiān)O(shè)備號(hào) ?
  • ????if?(result?<?0)? ?
  • ????{ ?
  • ????????printk(KERN_WARNING?"DEMO:?can't?get?major?%d\n",?simple_MAJOR); ?
  • ????????return?result; ?
  • ????} ?
  • ????simple_devices?=?kmalloc(sizeof(struct?simple_dev),?GFP_KERNEL); ?
  • ????if?(!simple_devices) ?
  • ????{ ?
  • ????????result?=?-ENOMEM; ?
  • ????????goto?fail; ?
  • ????} ?
  • ????memset(simple_devices,?0,?sizeof(struct?simple_dev)); ?
  • ????//初始化設(shè)備結(jié)構(gòu) ?
  • ????cdev_init(&simple_devices->cdev,?&simple_fops); ?
  • ????simple_devices->cdev.owner?=?THIS_MODULE; ?
  • ????simple_devices->cdev.ops?=?&simple_fops; ?
  • ????result?=?cdev_add?(&simple_devices->cdev,?dev,?1);//添加字符設(shè)備 ?
  • ????if(result) ?
  • ????{ ?
  • ????????printk(KERN_NOTICE?"Error?%d?adding?DEMO\n",?result); ?
  • ????????goto?fail; ?
  • ????} ?
  • ????return?0; ?
  • fail: ?
  • ????simple_cleanup_module(); ?
  • ????return?result; ?
  • } ?
  • module_init(simple_init_module); ?
  • module_exit(simple_cleanup_module); ?
  • 本例的應(yīng)用層代碼與運(yùn)行結(jié)果同上例。 與50位技術(shù)專家面對(duì)面20年技術(shù)見(jiàn)證,附贈(zèng)技術(shù)全景圖

    總結(jié)

    以上是生活随笔為你收集整理的使用cdev_add注册字符设备的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。