标签:blog .net details check replace lan 字符设备 sys kobject
本文详细介绍字符设备驱动,使用linux-4.8.2版本代码。
备注:
[todo]
1 static int chrdev_open(struct inode *inode, struct file *filp) 2 { 3 const struct file_operations *fops; 4 struct cdev *p; 5 struct cdev *new = NULL; 6 int ret = 0; 7 8 spin_lock(&cdev_lock); 9 p = inode->i_cdev; 10 if (!p) {//第一次打开时进入 11 struct kobject *kobj; 12 int idx; 13 spin_unlock(&cdev_lock); 14 kobj = kobj_lookup(cdev_map, inode->i_rdev, &idx);//在cdev_map中找到kobj 15 if (!kobj) 16 return -ENXIO; 17 new = container_of(kobj, struct cdev, kobj);//找到cdev 18 spin_lock(&cdev_lock); 19 /* Check i_cdev again in case somebody beat us to it while 20 we dropped the lock. */ 21 p = inode->i_cdev; 22 if (!p) { 23 inode->i_cdev = p = new; 24 list_add(&inode->i_devices, &p->list); 25 new = NULL; 26 } else if (!cdev_get(p)) 27 ret = -ENXIO; 28 } else if (!cdev_get(p)) 29 ret = -ENXIO; 30 spin_unlock(&cdev_lock); 31 cdev_put(new); 32 if (ret) 33 return ret; 34 35 ret = -ENXIO; 36 fops = fops_get(p->ops); 37 if (!fops) 38 goto out_cdev_put; 39 40 replace_fops(filp, fops);//绑定驱动的fops到filp上 41 if (filp->f_op->open) { 42 ret = filp->f_op->open(inode, filp);//调用驱动的open 43 if (ret) 44 goto out_cdev_put; 45 } 46 47 return 0; 48 49 out_cdev_put: 50 cdev_put(p); 51 return ret; 52 }
[todo]
字符设备结构体cdev的添加步骤:
cdev初始化:cdev_init,该函数将file_operations与cdev对应起来;
向kernel添加:cdev_add,该函数将主设备号与cdev结构体对应起来,由此主设备号对应驱动程序;(设备节点对应的是文件两码事,ALSA字符设备)
当对open设备节点时,首先通过节点找到主设备号,然后再kernel中搜索与主设备号相对应的字符设备cdev,然后动过cdev中file_operations结构体定义的open方法(这个open是需要自己实现的);
1 int kobj_map(struct kobj_map *domain, dev_t dev, unsigned long range, 2 struct module *module, kobj_probe_t *probe, 3 int (*lock)(dev_t, void *), void *data) 4 { 5 unsigned n = MAJOR(dev + range - 1) - MAJOR(dev) + 1; 6 unsigned index = MAJOR(dev);//取得主设备号 7 unsigned i; 8 struct probe *p; 9 10 if (n > 255) 11 n = 255; 12 13 p = kmalloc_array(n, sizeof(struct probe), GFP_KERNEL); 14 if (p == NULL) 15 return -ENOMEM; 16 17 for (i = 0; i < n; i++, p++) { 18 p->owner = module; 19 p->get = probe; 20 p->lock = lock; 21 p->dev = dev; 22 p->range = range; 23 p->data = data; 24 } 25 mutex_lock(domain->lock); 26 for (i = 0, p -= n; i < n; i++, p++, index++) { 27 struct probe **s = &domain->probes[index % 255]; 28 while (*s && (*s)->range < range) 29 s = &(*s)->next; 30 p->next = *s; 31 *s = p; 32 } 33 mutex_unlock(domain->lock); 34 return 0; 35 }
参考:
1.Multiconflictism的《Linux设备管理(二)_从cdev_add说起》,http://www.cnblogs.com/xiaojiang1025/p/6196198.html
2.cuijiyue的《主设备号--驱动模块与设备节点联系的纽带》http://blog.csdn.net/cuijiyue/article/details/42066425
2017-06-08
标签:blog .net details check replace lan 字符设备 sys kobject
原文地址:http://www.cnblogs.com/mapleay/p/6962071.html