中可找到,其定義如下:引用structcdev{structkobjectkobj;structmodule*owner;conststructfile_operations*ops;structlist_headlist;dev_tdev;unsignedintcount;};cdev結(jié)構(gòu)體中的dev_t成員定義了設(shè)備號,為32位,其中高12位為主設(shè)備號" />

亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

cdev 結(jié)構(gòu)體與字符設(shè)備的注冊

系統(tǒng) 1586 0

在 linux 2.6內(nèi)核中,使用 cdev結(jié)構(gòu)體描述字符設(shè)備,cdev 的定義在 <linux/cdev.h> 中可找到,其定義如下:
引用
struct cdev {
??????? struct kobject kobj;
??????? struct module *owner;
??????? const struct file_operations *ops;
??????? struct list_head list;
??????? dev_t dev;
??????? unsigned int count;
};

cdev 結(jié)構(gòu)體中的 dev_t 成員定義了設(shè)備號,為 32 位,其中高 12 位為主設(shè)備號,低 20 位為次設(shè)備號。
其中,struct kobject 是內(nèi)嵌的 kobject 對象;
??????????? struct module 是所屬模塊;
??????????? struct file_operations 為文件操作結(jié)構(gòu)體。

使用以下宏可以從 dev_t 獲得主設(shè)備號和次設(shè)備號:
引用
??????? MAJOR (dev_t dev);
??????? MINOR (dev_t dev);

而使用下面宏可以通過主設(shè)備號和次設(shè)備號生成 dev_t? :
引用
MKDEV (int major, int minor);

?

有兩個方法可以分配并初始化 cedv 結(jié)構(gòu)。如果希望在運行時動態(tài)的獲得一個獨立的 cdev 結(jié)構(gòu),可以如下這么做:
引用
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &my_fops;

cdev_alloc(void) 函數(shù)的代碼為(對 cdev 結(jié)構(gòu)體操作的系列函數(shù)可在 fs/char_dev.c 中找到):
引用
struct cdev *cdev_alloc(void)
{
??????? struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);
??????? if (p) {
??????????????? INIT_LIST_HEAD(&p->list);
??????????????? kobject_init(&p->kobj, &ktype_cdev_dynamic);
??????? }
??????? return p;
}

cdev_alloc() 的源代碼可能由于內(nèi)核版本號的不同而有差別(上面的代碼為 2.6.30)

有時可能希望就把 cdev 結(jié)構(gòu)內(nèi)嵌在自己的特定設(shè)備結(jié)構(gòu)里,那么在分配好 cdev 結(jié)構(gòu)后,就用 cdev_init() 函數(shù)對其初始化:
引用
void cdev_init (struct cdev *cdev, struct file_operations *fops)

cdev_init() 函數(shù)代碼為:
引用
void cdev_init(struct cdev *cdev, const struct file_operations *fops)
{
??????? memset(cdev, 0, sizeof *cdev);
??????? INIT_LIST_HEAD(&cdev->list);
??????? kobject_init(&cdev->kobj, &ktype_cdev_default);
??????? cdev->ops = fops;
}

另外,像 cdev 中的 owner 要設(shè)置為 THIS_MOULE 。
一旦 cdev 結(jié)構(gòu)體設(shè)置完畢,最后一步就是要把這事告訴給內(nèi)核,使用下面的函數(shù):
引用
int cdev_add(struct cdev *p, dev_t dev, unsigned count)

cdev_add() 對應(yīng)的代碼為:
引用
/**
* cdev_add() - add a char device to the system
* @p: the cdev structure for the device
* @dev: the first device number for which this device is responsible
* @count: the number of consecutive minor numbers corresponding to this
*???????? device
*
* cdev_add() adds the device represented by @p to the system, making it
* live immediately.? A negative error code is returned on failure.
*/
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
??????? p->dev = dev;
??????? p->count = count;
??????? return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}

參數(shù) p 是 cdev 結(jié)構(gòu)體的指針;
參數(shù) dev 是設(shè)備響應(yīng)的第一個設(shè)備號;
參數(shù) count 和設(shè)備相關(guān)聯(lián)的設(shè)備號的數(shù)目。
一般的,count 的值為 1,但是有些情形也可能是大于 1 的數(shù)。比如 SCSI 磁帶機(jī),它通過給每個物理設(shè)備安排多個此設(shè)備號來允許用戶在應(yīng)用程序里選擇操作模式(比如密度)。

cdev_add 如果失敗了,那么返回一個負(fù)值,表明驅(qū)動無法加載到系統(tǒng)中。然而它一般情況下都會成功,一旦 cdev_add 返回,設(shè)備也就 “活” 了起來,于是所對應(yīng)的操作方法(file_operations 結(jié)構(gòu)里所定義的各種函數(shù))也就能為內(nèi)核所調(diào)用。

從系統(tǒng)中移除一個字符設(shè)備,可以調(diào)用:
引用
void cdev_del(struct cdev *p)

?

老版本的字符設(shè)備注冊與注銷
在許多驅(qū)動程序代碼里,會看到許多字符設(shè)備驅(qū)動并沒有用 cdev 這個接口。這是一種老式的方法,但新寫的代碼應(yīng)該使用 cdev 接口。

用于注冊字符設(shè)備驅(qū)動程序的老式函數(shù) register_chrdev() 函數(shù)定義如下:
引用
int register_chardev (unsigned int major, const char *name, struct file_operations *fops)

利用該函數(shù)注冊時,應(yīng)先定義好主設(shè)備號、設(shè)備驅(qū)動程序的名稱、file_operations 結(jié)構(gòu)體的變量。

應(yīng)用程序中利用設(shè)備文件搜索設(shè)備驅(qū)動程序的時候使用主設(shè)備號 (major) 。

在內(nèi)核中表示 proc 文件系統(tǒng)或錯誤代碼時,使用設(shè)備驅(qū)動程序名稱。

另外,利用 unregister_chrdev() 函數(shù)注銷字符設(shè)備驅(qū)動程序時,可以作為區(qū)分標(biāo)志。注冊函數(shù)中關(guān)鍵的地方是定義 file_operations 結(jié)構(gòu)體變量的地址。

所謂注冊字符設(shè)備驅(qū)動程序,應(yīng)理解為在內(nèi)核中注冊與主設(shè)備號相關(guān)的 file_operations 結(jié)構(gòu)體。

register_chrdev() 函數(shù)注冊完設(shè)備驅(qū)動程序,把定義主設(shè)備號的 major 設(shè)置為 0,返回注冊的主設(shè)備號(動態(tài)分配),把已知的主設(shè)備號設(shè)為 major 值時,返回 0 (人工指定)。注冊失敗時,返回負(fù)值

從內(nèi)核中注銷字符設(shè)備驅(qū)動程序的 unregister_chrdev() 函數(shù)形式如下:
引用
int unregister_chrdev (unsigned int major, const char *name)

該函數(shù)中使用主設(shè)備號(major) 和設(shè)備驅(qū)動程序名稱 (name) 與 register_chrdev 函數(shù)中使用的值相同,因為內(nèi)核會把這些參數(shù)作為注銷字符設(shè)備驅(qū)動程序的基準(zhǔn)對比兩個設(shè)定內(nèi)容。從內(nèi)核成功注銷了字符設(shè)備驅(qū)動程序時,返回 0 ,失敗則返回負(fù)值。

cdev 結(jié)構(gòu)體與字符設(shè)備的注冊


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 中国大乳久久 | 亚洲综合首页 | 天堂网在线观看 | 伊人热人久久中文字幕 | 四虎2021地址入口 | 久久性生活视频 | 欧美日韩亚洲国产一区二区综合 | 免费h片在线观看 | 免费福利影院 | 日韩一区二区不卡中文字幕 | 亚洲国产乱 | 国产福利观看 | 国产一区二区精品久久91 | 美女视频免费在线观看 | 久久久久久久国产精品影院 | 天啪天天久久天天综合啪 | 国产在线精品一区二区 | 久久加久久 | 久久激情综合色丁香 | 精品一区二区三区四区乱码90 | 99久久国产免费中文无字幕 | 久久精品成人 | 欧美精品成人免费视频 | 欧美日韩综合视频 | 国产成人精品一区二区视频 | 精品69久久久久久99 | 国产精品视频网 | 狠狠色丁婷婷综合久久 | 青青青爽视频在线观看入口 | 久久久久久久国产精品影院 | 国产在线观看一区二区三区 | 91尤物在线视频 | 视频二区中文字幕 | 国产成人永久免费视 | 四虎最新网站 | 亚洲高清毛片 | 久久亚洲国产成人精品性色 | 香蕉网站在线观看 | 伊人久久大杳蕉综合大象 | 久久精品一区二区国产 | 伊人网综合视频 |