日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國內(nèi)最全I(xiàn)T社區(qū)平臺 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁 > php開源 > 綜合技術(shù) > linux系統(tǒng)中misc子系統(tǒng)

linux系統(tǒng)中misc子系統(tǒng)

來源:程序員人生   發(fā)布時(shí)間:2015-01-23 08:59:14 閱讀次數(shù):8212次

misc子系統(tǒng)


轉(zhuǎn)載請注明出處:http://blog.csdn.net/wang_zheng_kai

光源器件與系統(tǒng)研究所

個(gè)人學(xué)習(xí)總結(jié)

1、在linux系統(tǒng)中甚么是misc?

         在研究攝像頭驅(qū)動(dòng)的時(shí)候,發(fā)現(xiàn)攝像頭驅(qū)動(dòng)的路徑為:/driver/misc/jz_cim/文件目錄下,經(jīng)過查找結(jié)果以下:

         雜項(xiàng)裝備(misc device)

         雜項(xiàng)裝備也是嵌入式系統(tǒng)中用得比較多的1種裝備驅(qū)動(dòng)。在 Linux 內(nèi)核的include/linux目錄下有miscdevice.h文件,要把自己定義的misc device從裝備定義在這里。實(shí)際上是由于這些字符裝備不符合預(yù)先肯定的字符裝備范疇,所有這些裝備采取主編號10 ,1起歸于misc device,其實(shí)misc_register就是用主標(biāo)號10調(diào)用register_chrdev()的,只不過misc是將1些字符裝備寄存在misc類中。換句話說,misc裝備其實(shí)也就是特殊的字符裝備。

        

2、linux內(nèi)核雜項(xiàng)裝備驅(qū)動(dòng)源碼分析

       在Linux驅(qū)動(dòng)中把沒法歸類的5花8門的裝備定義為混雜裝備(用miscdevice結(jié)構(gòu)體表述)。miscdevice同享1個(gè)主裝備號MISC_MAJOR(即10),但次裝備號不同。所有的miscdevice裝備構(gòu)成了1個(gè)鏈表,對裝備訪問時(shí)內(nèi)核根據(jù)次裝備號查找對應(yīng)的miscdevice裝備,然后調(diào)用其file_operations結(jié)構(gòu)中注冊的文件操作接口進(jìn)行操作。在內(nèi)核中用struct miscdevice表示miscdevice裝備,然后調(diào)用其file_operations結(jié)構(gòu)中注冊的文件操作接口進(jìn)行操作。miscdevice的API實(shí)現(xiàn)在drivers/char/misc.c中,misc裝備的初始化,注冊,注銷都在這個(gè)文件中。在內(nèi)核中,misc雜項(xiàng)裝備驅(qū)動(dòng)接口是對1些字符裝備的簡單封裝,他們同享1個(gè)主裝備號,有不同的次裝備號,同享1個(gè)open調(diào)用,其他的操作函數(shù)在打開后應(yīng)用linux驅(qū)動(dòng)程序的方法重載進(jìn)行裝載。

 

我們首先先來看misc裝備的結(jié)構(gòu)體的描寫:

         代碼位于:android⑷.1/kernel/include/linux/miscdevice.h,該文件中還有所有misc裝備的次裝備號的宏定義。

struct miscdevice { intminor; //次裝備號 const char*name; //裝備的名稱 const structfile_operations *fops; //文件操作 structlist_head list; //misc_list的鏈表頭 struct device*parent; //父裝備(Linux裝備模型中的東東了,哈哈) struct device*this_device; //當(dāng)前裝備,是device_create的返回值,下邊會(huì)看到 constchar *nodename; mode_tmode; };

         這個(gè)結(jié)構(gòu)體是misc裝備基本的結(jié)構(gòu)體,在注冊misc裝備的時(shí)候必須要聲明并初始化1個(gè)這樣的結(jié)構(gòu)體,但其中1般只需填充name minor fops字段就能夠了。下面就是led驅(qū)動(dòng)程序中初始化miscdevice的代碼:

static struct miscdevice misc = { .minor =MISC_DYNAMIC_MINOR, .name =DEVICE_NAME, .fops =&dev_fops, };

    1般的時(shí)候在fops不用實(shí)現(xiàn)open方法,由于最初的方法misc_ops包括了open方法。其中minor如果填充MISC_DYNAMIC_MINOR,則是動(dòng)態(tài)次裝備號,次裝備號由misc_register動(dòng)態(tài)分配的。

 

然后來看看misc子系統(tǒng)的初始化函數(shù):

static int __init misc_init(void) { int err; #ifdef CONFIG_PROC_FS proc_create("misc", 0, NULL,&misc_proc_fops); /*創(chuàng)建1個(gè)proc入口項(xiàng)*/ #endif misc_class =class_create(THIS_MODULE, "misc"); /*在/sys/class/目錄下創(chuàng)建1個(gè)名為misc的類*/ err = PTR_ERR(misc_class); if(IS_ERR(misc_class)) gotofail_remove; err =-EIO; /*注冊裝備,其中裝備的主裝備號為MISC_MAJOR,為10。裝備名為misc,misc_fops是操作函數(shù)的集合*/ if(register_chrdev(MISC_MAJOR,"misc",&misc_fops)) gotofail_printk; misc_class->devnode= misc_devnode; return0; fail_printk: printk("unable to get major %d for misc devices/n",MISC_MAJOR); class_destroy(misc_class); fail_remove: remove_proc_entry("misc", NULL); returnerr; } subsys_initcall(misc_init); /*misc作為1個(gè)子系統(tǒng)被注冊到linux內(nèi)核中*/

         可以看出,這個(gè)初始化函數(shù),最主要的功能就是注冊字符裝備 ,所用的注冊接口是2.4內(nèi)核的register_chrdev。它注冊了主裝備號為MISC_MAJOR,次裝備號為0⑵55的256個(gè)裝備。并且創(chuàng)建了1個(gè)misc類。

 

下邊是register_chrdev函數(shù)的實(shí)現(xiàn):

int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops) { structchar_device_struct *cd; struct cdev*cdev; char *s; int err =-ENOMEM; /*主裝備號是10,次裝備號為從0開始,分配256個(gè)裝備*/ cd =__register_chrdev_region(major, 0, 256, name); if(IS_ERR(cd)) returnPTR_ERR(cd); /*分配字符裝備*/ cdev =cdev_alloc(); if(!cdev) gotoout2; cdev->owner = fops->owner; cdev->ops= fops; /*Linux裝備模型中的,設(shè)置kobject的名字*/ kobject_set_name(&cdev->kobj, "%s", name); for (s =strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) *s ='!'; /*把這個(gè)字符裝備注冊到系統(tǒng)中*/ err =cdev_add(cdev, MKDEV(cd->major, 0), 256); if (err) gotoout; cd->cdev =cdev; return major? 0 : cd->major; out: kobject_put(&cdev->kobj); out2: kfree(__unregister_chrdev_region(cd->major, 0, 256)); returnerr; } 來看看這個(gè)裝備的操作函數(shù)的集合: static const struct file_operations misc_fops = { .owner =THIS_MODULE, .open = misc_open, };

可以看到這里只有1個(gè)打開函數(shù),用戶打開miscdevice裝備是通過主裝備號對應(yīng)的打開函數(shù),在這個(gè)函數(shù)中找到次裝備號對應(yīng)的相應(yīng)的具體裝備的open函數(shù)。它的實(shí)現(xiàn)以下:

 

static int misc_open(struct inode * inode,struct file * file) { intminor = iminor(inode); structmiscdevice *c; interr = -ENODEV; const struct file_operations *old_fops, *new_fops = NULL; lock_kernel(); mutex_lock(&misc_mtx); /*找到次裝備號對應(yīng)的操作函數(shù)集合,讓new_fops指向這個(gè)具體裝備的操作函數(shù)集合*/ list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { new_fops = fops_get(c->fops); break; } } if(!new_fops) { mutex_unlock(&misc_mtx); /*如果沒有找到,則要求加載這個(gè)次裝備號對應(yīng)的模塊*/ request_module("char-major-%d-%d", MISC_MAJOR, minor); mutex_lock(&misc_mtx); /*重新遍歷misc_list鏈表,如果沒有找到就退出,否則讓new_fops指向這個(gè)具體裝備的操作函數(shù)集合*/ list_for_each_entry(c, &misc_list, list) { if (c->minor == minor) { new_fops =fops_get(c->fops); break; } } if (!new_fops) goto fail; } err= 0; /*保存舊打開函數(shù)的地址*/ old_fops = file->f_op; /*讓主裝備號的操作函數(shù)集合指針指向具體裝備的操作函數(shù)集合*/ file->f_op = new_fops; if(file->f_op->open) { /*使用具體裝備的打開函數(shù)打開裝備*/ 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); fail: mutex_unlock(&misc_mtx); unlock_kernel(); return err; }


再來看看misc子系統(tǒng)對外提供的兩個(gè)重要的API,misc_register,misc_deregister:

         misc_register()函數(shù)在misc.c中,最主要的功能是基于misc_class構(gòu)造1個(gè)裝備,將miscdevice結(jié)構(gòu)掛載到misc_list列表上,并初始化與linux裝備模型相干的結(jié)構(gòu),它的參數(shù)是miscdevice結(jié)構(gòu)體。

int misc_register(struct miscdevice *misc) { struct miscdevice *c; dev_t dev; interr = 0; INIT_LIST_HEAD(&misc->list); //鏈表項(xiàng)使用時(shí)必須初始化 mutex_lock(&misc_mtx); /*遍歷misc_list鏈表,看這個(gè)次裝備號之前有無被用過,如果次裝備號已被占有則退出*/ list_for_each_entry(c, &misc_list, list) { if (c->minor == misc->minor) { mutex_unlock(&misc_mtx); return -EBUSY; } } /*看是不是是需要?jiǎng)討B(tài)分配次裝備號*/ if(misc->minor == MISC_DYNAMIC_MINOR) { /* *#define DYNAMIC_MINORS 64 /* like dynamic majors */ *static unsigned char misc_minors[DYNAMIC_MINORS / 8]; *這里存在1個(gè)次裝備號的位圖,1共64位。下邊是遍歷每位, *如果這位為0,表示沒有被占有,可使用,為1表示被占用。 */ int i = DYNAMIC_MINORS; while (--i >= 0) if ( (misc_minors[i>>3] & (1 << (i&7))) == 0) break; if (i<0) { mutex_unlock(&misc_mtx); return -EBUSY; } /*得到這個(gè)次裝備號*/ misc->minor = i; } /*設(shè)置位圖中相應(yīng)位為1*/ if(misc->minor < DYNAMIC_MINORS) misc_minors[misc->minor >> 3] |= 1 << (misc->minor& 7); /*計(jì)算出裝備號*/ dev= MKDEV(MISC_MAJOR, misc->minor); /*在/dev下創(chuàng)建裝備節(jié)點(diǎn),這就是有些驅(qū)動(dòng)程序沒有顯式調(diào)用device_create,卻出現(xiàn)了裝備節(jié)點(diǎn)的緣由*/ misc->this_device = device_create(misc_class, misc->parent, dev,NULL, "%s",misc->name); if(IS_ERR(misc->this_device)) { err = PTR_ERR(misc->this_device); goto out; } /* *Add it to the front, so that later devices can "override" *earlier defaults */ /*將這個(gè)miscdevice添加到misc_list鏈表中*/ list_add(&misc->list, &misc_list); out: mutex_unlock(&misc_mtx); return err; }


可以看出,這個(gè)函數(shù)首先遍歷misc_list鏈表,查找所用的次裝備號是不是已被注冊,避免沖突。如果是動(dòng)態(tài)次裝備號則分配1個(gè),然后調(diào)用MKDEV生成裝備號,從這里可以看出所有的misc裝備同享1個(gè)主裝備號MISC_MAJOR,然后調(diào)用device_create,生成裝備文件。最后加入到misc_list鏈表中。

    關(guān)于device_create,class_create 作用: class_create函數(shù)在misc.c中的模塊初始化中被調(diào)用,現(xiàn)在1起說1下。這兩個(gè)函數(shù)看起來很陌生,沒有在ldd3中發(fā)現(xiàn)過,看源代碼的時(shí)候發(fā)現(xiàn)class_create會(huì)調(diào)用底層組件__class_regsiter()是說明它是注冊1個(gè)類。而device_create是創(chuàng)建1個(gè)裝備,他是創(chuàng)建裝備的便捷實(shí)現(xiàn)調(diào)用了device_register函數(shù)。他們都提供給linux裝備模型使用,從linux內(nèi)核2.6的某個(gè)版本以后,devfs不復(fù)存在,udev成為devfs的替換。相比devfs,udev有很多優(yōu)勢。

struct class *myclass =class_create(THIS_MODULE, “my_device_driver”); 

class_device_create(myclass, NULL,MKDEV(major_num, 0), NULL, “my_device”); 

   這樣就創(chuàng)建了1個(gè)類和裝備,模塊被加載時(shí),udev daemon就會(huì)自動(dòng)在/dev下創(chuàng)建my_device裝備文件節(jié)點(diǎn)。這樣就省去了自己創(chuàng)建裝備文件的麻煩。這樣也有助于動(dòng)態(tài)裝備的管理.

這個(gè)是miscdevice的卸載函數(shù):

int misc_deregister(struct miscdevice*misc) { inti = misc->minor; if(list_empty(&misc->list)) return -EINVAL; mutex_lock(&misc_mtx); /*在misc_list鏈表中刪除miscdevice裝備*/ list_del(&misc->list); /*刪除裝備節(jié)點(diǎn)*/ device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor)); if(i < DYNAMIC_MINORS && i>0) { /*釋放位圖相應(yīng)位*/ misc_minors[i>>3] &= ~(1 << (misc->minor &7)); } mutex_unlock(&misc_mtx); return 0; }

總結(jié)1下miscdevice驅(qū)動(dòng)的注冊和卸載流程:

misc_register:匹配次裝備號->找到1個(gè)沒有占用的次裝備號(如果需要?jiǎng)討B(tài)分配的話)->計(jì)算裝備號->創(chuàng)建裝備文件->miscdevice結(jié)構(gòu)體添加到misc_list鏈表中。

misc_deregister:從mist_list中刪除miscdevice->刪除裝備文件->位圖位清零。

 

總結(jié):

雜項(xiàng)裝備作為字符裝備的封裝,為字符裝備提供的簡單的編程接口,如果編寫新的字符驅(qū)動(dòng),可以斟酌使用雜項(xiàng)裝備接口,方便簡單,只需要初始化1個(gè)miscdevice的結(jié)構(gòu),調(diào)用misc_register就能夠了。系統(tǒng)最多有255個(gè)雜項(xiàng)裝備,由于雜項(xiàng)裝備模塊自己占用了1個(gè)次裝備號

生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 自拍偷拍在线视频 | 欧美福利网 | 国产成人精品a视频一区www | 久久精品一区二区三区不卡牛牛 | 欧美日韩在线第一页 | av在线一区二区 | 日本一区二区三区免费观看 | 一级片av| 欧美日韩国产一区二区三区 | 久久九九免费视频 | 一区二区国产视频 | 欧美日韩国产大片 | 国产小视频在线播放 | 免费日韩一区二区 | 亚洲午夜网 | 日韩精品成人 | 欧美精品久久久久久久免费软件 | 国产偷久久一级精品60部 | 天天久久| 精品久久久久久 | 一本色道精品久久一区二区三区 | 中文字幕日本视频 | 欧美天堂| 亚洲国产精品电影 | 夜夜福利| 偷拍导航 | 欧美 日韩 综合 | 黄色三级免费看 | 国产伦精品一区二区三区高清版 | 97成人在线视频 | 免费污污网站 | 国产精品久久久久久久久久久免费看 | 韩国精品久久久 | 亚洲福利网 | 成人免费一区二区三区视频网站 | 国产区一区二区三区 | 一区二区三区久久久 | 一区二区三区在线播放 | 国产精品爽爽爽爽爽爽在线观看 | 69视频免费在线观看 | 欧美精品一区二区三区视频 |