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

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

[置頂] 圖解linux char驅(qū)動

來源:程序員人生   發(fā)布時間:2015-01-06 09:04:05 閱讀次數(shù):3319次

                                                                             圖解Linux char 驅(qū)動

 主題:                                                                                                                                                                               
   1.字符驅(qū)動模型。
   2.字符裝備的裝備號。
   3.文件系統(tǒng)中對字符裝備的訪問。

   1:字符裝備框架
 
        寫的驅(qū)動程序只是1個程序,
        然后將底層硬件驅(qū)動抽象出來用1個結(jié)構(gòu)體來表示cdev。
        那末我們需要做的就是從用戶空間寫的open、write、read等系統(tǒng)調(diào)用來操作硬件,
        通過系統(tǒng)調(diào)用進(jìn)入內(nèi)核,而內(nèi)核的實現(xiàn)就是利用了1切皆文件的思想,
       就是上層直接操作文件但實質(zhì)底層就是在操作硬件,
     這個轉(zhuǎn)換就是VFS。
   
  2:大概的進(jìn)程:
    大概進(jìn)程就是說open(“/dev/first_drv”,..)
    會進(jìn)入內(nèi)核->創(chuàng)建1個file結(jié)構(gòu)體->該結(jié)構(gòu)體指向->inode
    ->通過主裝備號查找到cdev結(jié)構(gòu)(即是驅(qū)動)->找到cdev指向的操作函數(shù)指針->找到.open->自己的open函數(shù)。
   
  3:下面是相干的詳細(xì)說明底層如何實現(xiàn):
  相干數(shù)據(jù)結(jié)構(gòu):

25 struct cdev { 26 struct kobject kobj; 27 struct module *owner; 28 const struct file_operations *ops; 29 struct list_head list; 30 dev_t dev; 31 unsigned int count; 32 }; 33 34 struct kobj_map { 35 36 struct probe { 37 38 struct probe *next; 39 dev_t dev; 40 unsigned long range; 41 struct module *owner; 42 kobj_probe_t *get; 43 int (*lock)(dev_t, void *); 44 void *data; 45 } *probes[255]; 46 struct mutex *lock; 47 }; 48 49 static struct char_device_struct { 50 51 struct char_device_struct *next; 52 unsigned int major; 53 unsigned int baseminor; 54 int minorct; 55 char name[64]; 56 struct file_operations *fops; 57 struct cdev *cdev; /* will die */ 58 } *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; 59 60 #define CHRDEV_MAJOR_HASH_SIZE 255


 1.字符裝備驅(qū)動模型。
    每個字符設(shè)驅(qū)動有1個cdev結(jié)構(gòu)提表示。
    再裝備驅(qū)動模型那個(device driver model)中。使用(kobject mapping domain)
    來記錄字符裝備文件驅(qū)動。這是由struct kobj_map結(jié)構(gòu)體來表示。
    它內(nèi)嵌了255個struct probe指針數(shù)組。kobj_map由全局變量cdev_map援用。
    static struct kobj_map *cdev_map; 這個全局變量的定義在char_dev.c中。

70 /------------- 71 | cdev_map | 72 -------------/ 73 | 74 | /------> probe /------> probe 75 | | +---------+ | +---------+ /------- 76 | | | *next |----/ | *next |----->| NULL | 77 --->kobj_map | +---------+ +---------+ -------/ 78 +-------------------+ | | dev | | dev | 79 | *probes[255] | | +---------+ +---------+ 80 | +-----------+ | | | range | | range | 81 | | *probe | | | +---------+ +---------+ 82 | +-----------+ | | | *owner | | *owner | 83 | | *probe |---------/ +---------+ +---------+ 84 | +-----------+ | | *get | | *get | 85 | | .... | | +---------+ +---------+ 86 | +-----------+ | | *lock | | *lock | 87 | | *probe | | +---------+ +---------+ 88 | +-----------+ | | *data |------ | *data |------ 89 | | *probe |--------- +---------+ | +---------+ | 90 | +-----------+ | | | | 91 +------------------- | | | 92 | | | 93 | | | 94 | /------- | | 95 ----->| NULL | | | 96 -------/ | | 97 | | 98 cdev<-----------/ cdev<----/ 99 +---------+ +---------+ 100 | *kobj | | *kobj | 101 +---------+ +---------+ 102 | *owner | | *owner | 103 +---------+ +---------+ 104 | *ops | | *ops | 105 +---------+ +---------+ 106 | *list | | *list | 107 +---------+ +---------+ 108 | dev | | dev | 109 +---------+ +---------+ 110 | *count | | *count | 111 +---------+ +---------+


1:cdev_add()函數(shù)詳解。

1.

  1般會使用kzalloc(size,GFP_KERNEL)給cdev分配1塊空間,然后初始化好,ops對應(yīng)的結(jié)構(gòu)體。  

2.
  再使用cdev_init把ops函數(shù)操作集和cdev綁定起來。
 
3.
   使用cdev_add() 用來將cdev對象添加到驅(qū)動模型中,其主要是通過kobj_map()來實現(xiàn)的.
kobj_map() 會創(chuàng)建1個probe對象,然后將其插入cdev_map中的某1項中,并關(guān)聯(lián)probe->data 指向 cdev

 4.

   struct kobject *kobj_lookup(struct kobj_map *domain, dev_t dev, int *index)
根據(jù)裝備號,在cdev_map中查找其cdev對象內(nèi)嵌的kobject. (probe->data->kobj),返回的是cdev的kobject

int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, 133 struct module *module, kobj_probe_t *probe, 134 int (*lock)(dev_t, void *), void *data) 135 { 136 137 unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; 138 unsigned index = MAJOR(dev); 139 unsigned i; 140 struct probe *p; 141 142 if (n > 255) 143 n = 255; 144 //為prob結(jié)構(gòu)體分配空間。 145 p = kmalloc(sizeof(struct probe) * n, GFP_KERNEL); 146 if (p == NULL) 147 return -ENOMEM; 148 149 //給結(jié)構(gòu)體賦值。 150 for (i = 0; i < n; i++, p++) { 151 p->owner = module; 152 p->get = probe; 153 p->lock = lock; 154 p->dev = dev; 155 p->range = range; 156 p->data = data; 157 } 158 mutex_lock(domain->lock); 159 160 //把分配的結(jié)構(gòu)體probe寄存到該hash表中。結(jié)構(gòu)如上。 161 for (i = 0, p -= n; i < n; i++, p++, index++) { 162 struct probe **s = &domain->probes[index % 255]; 163 while (*s && (*s)->range < range) 164 s = &(*s)->next; 165 p->next = *s; 166 *s = p; 167 } 168 mutex_unlock(domain->lock); 169 return 0; 170 }



 2:字符裝備的裝備號。


174 0 1 2 253 254 175 +--------+--------+--------+--------+--------+-------- 176 cdevs | | | | .... | | | 177 +--------+--------+--------+--------+--------+-------- 178 | | | | 179 | | | | 180 | | | | 181 /------- | | | | 182 | NULL |<--/ | | | 183 -------/ | | | /------- 184 | | ------>| NULL | 185 | | -------/ 186 /-----------------/ /------- 187 | | NULL | 188 | -------/ 189 | 190 ------>char_devices_struct /----> char_devices_struct 191 +----------------+ | +----------------+ /------- 192 | *next |--------/ | *next |------>| NULL | 193 +----------------+ +----------------+ -------/ 194 | major | | major | 195 +----------------+ +----------------+ 196 | vaseminor | | vaseminor | 197 +----------------+ +----------------+ 198 | *name[64] | | *name[64] | 199 +----------------+ +----------------+ 200 | *fops | | *fops | 201 +----------------+ +----------------+ 202 | *cdev | | *cdev | 203 +----------------+ +----------------+

 字符裝備的主,次裝備號的分配:

 1.
    全局?jǐn)?shù)組 chrdevs 包括了255(CHRDEV_MAJOR_HASH_SIZE 的值)個struct char_device_struct的元素.
 每個對應(yīng)1個相應(yīng)的主裝備號.

2.
  分配了1個裝備號,就會創(chuàng)建1個 struct char_device_struct 的對象,
并將其添加到chrdevs中.這樣,通過chrdevs數(shù)組,我們就能夠知道分配了哪些裝備號.

 相干函數(shù):
 1.  register_chrdev_region( ) 分配指定的裝備號范圍
  2.alloc_chrdev_region( ) 動態(tài)分配裝備范圍他們都主要是通過調(diào)用函數(shù)__register_chrdev_region() 來實現(xiàn)的
      要注意,這兩個函數(shù)僅僅是注冊裝備號! 如果要和cdev關(guān)聯(lián)起來,還要調(diào)用cdev_add()

   register_chrdev( ) 申請指定的裝備號,并且將其注冊到字符裝備驅(qū)動模型中.
  它所做的事情為:
   1. 注冊裝備號, 通過調(diào)用 __register_chrdev_region() 來實現(xiàn)
   2. 分配1個cdev, 通過調(diào)用 cdev_init()來實現(xiàn)
   3. 將cdev添加到驅(qū)動模型中,這1步將裝備號和驅(qū)動關(guān)聯(lián)了起來.通過調(diào)用 cdev_add() 來實現(xiàn)
   4. 將第1步中創(chuàng)建的 struct char_device_struct 對象的 cdev 指向第2步中分配的cdev. 由于register_chrdev()是老的接口,
       這1步在新的接口中其實不需要.

236 /-------------------------------------->cdev<------------------------------------ 237 | +---------+ | 238 | | *kobj | | 239 | +---------+ | 240 | | *owner | | 241 | +---------+ | 242 | | *ops | | 243 | +---------+ | 244 | /----------------------------->| *list |<--------------------------- | 245 | | +---------+ | | 246 | | | dev | | | 247 | | +---------+ | | 248 | | | *count | | | 249 | | +---------+ | | 250 | | | | 251 | | inode inode | | 252 | | +---------+ +---------+ | | 253 | | | i_rdev | | i_rdev | | | 254 | | +---------+ +---------+ | | 255 | ----------|i_devices|<----------.........--------->|i_devices|<------/ | 256 | +---------+ +---------+ | 257 --------------- |*i_cdev | |*i_cdev |------------/ 258 +---------+ +---------+ 259 |i_cindex | |i_cindex | 260 +---------+ +---------+ 261 | ..... | | ..... | 262 +---------+ +---------+

 

系統(tǒng)調(diào)用open打開1個字符裝備的時候, 通過1系列調(diào)用,終究會履行到 chrdev_open.
    (終究是通過調(diào)用到def_chr_fops中的.open, 而def_chr_fops.open = chrdev_open. 這1系列的調(diào)用進(jìn)程,本文暫不討論)

    int chrdev_open(struct inode * inode, struct file * filp)

     chrdev_open()所做的事情可以概括以下:
   1. 根據(jù)裝備號(inode->i_rdev), 在字符裝備驅(qū)動模型中查找對應(yīng)的驅(qū)動程序,
        這通過kobj_lookup() 來實現(xiàn), kobj_lookup()會返回對應(yīng)驅(qū)動程序cdev的kobject.   
    2. 設(shè)置inode->i_cdev , 指向找到的cdev  
    3. 將inode添加到cdev->list的鏈表中.
    4. 使用cdev的ops 設(shè)置file對象的f_op
    5. 如果ops中定義了open方法,則調(diào)用該open方法
    6. 返回.
  履行完chrdev_open()以后,file對象的f_op指向cdev的ops,因此以后對裝備進(jìn)行的read, write等操作,就會履行cdev的相應(yīng)操作.




285 static int chrdev_open(struct inode *inode, struct file *filp) 286 { 287 288 struct cdev *p; 289 struct cdev *new = NULL; 290 int ret = 0; 291 292 spin_lock(&cdev_lock); 293 p = inode->i_cdev; 294 if (!p) { 295 struct kobject *kobj; 296 int idx; 297 spin_unlock(&cdev_lock); 298 299 // 1. 根據(jù)裝備號(inode->i_rdev), 在字符裝備驅(qū)動模型中查找對應(yīng)的驅(qū)動程序, 300 //這通過kobj_lookup() 來實現(xiàn), kobj_lookup()會返回對應(yīng)驅(qū)動程序cdev的kobject. 301 302 kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx); 303 if (!kobj) 304 return -ENXIO; 305 new = container_of(kobj, struct cdev, kobj); 306 spin_lock(&cdev_lock); 307 /* Check i_cdev again in case somebody beat us to it while 308 we dropped the lock. */ 309 310 //2. 設(shè)置inode->i_cdev , 指向找到的cdev. 311 p = inode->i_cdev; 312 if (!p) { 313 inode->i_cdev = p = new; 314 315 //3. 將inode添加到cdev->list的鏈表中. 316 list_add(&inode->i_devices, &p->list); 317 318 new = NULL; 319 } else if (!cdev_get(p)) 320 ret = -ENXIO; 321 } else if (!cdev_get(p)) 322 ret = -ENXIO; 323 spin_unlock(&cdev_lock); 324 cdev_put(new); 325 if (ret) 326 return ret; 327 328 ret = -ENXIO; 329 330 //4. 使用cdev的ops 設(shè)置file對象的f_op 331 filp->f_op = fops_get(p->ops); 332 if (!filp->f_op) 333 goto out_cdev_put; 334 335 if (filp->f_op->open) { 336 5. 如果ops中定義了open方法,則調(diào)用該open方法 337 ret = filp->f_op->open(inode, filp); 338 if (ret) 339 goto out_cdev_put; 340 } 341 342 return 0; }


 
生活不易,碼農(nóng)辛苦
如果您覺得本網(wǎng)站對您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: av网站大全在线观看 | 精品在线一区二区三区 | 亚洲综合一区在线 | 日韩精品免费一区二区在线观看 | 2021国产精品视频 | 99国产精品一区 | www一区二区 | 欧美亚洲免费 | 日韩欧美一区二区三区 | 一级片黄色 | 一区二区三区高清在线观看 | 毛片高清 | 久久午夜影视 | 国产在线欧美 | 91网站免费看 | 国产精品性做久久久久久 | 久久欧美 | 欧美精品一区二区三区视频 | 日韩欧美大片网站 | a√毛片| 亚洲欧美成人网 | 日本aⅴ免费视频一区二区三区 | 日韩视频在线一区二区 | 黄色片网| 成人亚洲网站 | 91理论电影 | 国产精品久久久一区 | 午夜av免费在线观看 | 国产激情精品一区二区三区 | 高清不卡一区二区三区 | 亚洲精品久久久一区二区三区 | 99re国产| 黄色网页免费看 | 国产一区二区三区四区 | 91蝌蚪色| 天天摸夜夜 | 亚洲一二三四区 | 成人小视频在线 | 视频国产精品 | 国产噜噜噜噜噜久久久久久久久 | 久久久久久国产精品 |