云彩网站/图片seo优化是什么意思
在Linux驱动中,分为三种驱动:字符设备驱动,块设备驱动,网络驱动。其中字符设备,块设备的表示都是通过文件来进行表示的。则对它们这些设备的操作都是通过统一的系统调用open,read,write等,和普通文件的操作没任何区别,那这是如何操作到设备的呢。在这里我将进行详细的解说。
注意:我这里主要讲解的是2.6以后的版本的代码,2.4以前的由于过时了就不在讲解了。
以下是我讲解的结构:
1、揭秘设备的驱动在注册,添加的内核的时候,内核是如何操作的,安排他们的。
2、进程是如何和文件进行挂钩的。VFS机制
3、设备文件的系统调用open,read,wirte等,是如何调用到特定于设备的file_operations的。
第一节:揭秘设备的驱动在注册,添加的时候,内核是如何出来的。
因为篇幅有限这里主要讨论字符设备的情况,块设备的在下一节在分析。
先回忆一下字符设备的关键操作。。
1、先注册或分配一个设备号。或静态分配或动态分配
int register_chrdev_region(dev_t form,unsigned count,const
char *name);//静态
int alloc_chrdev_region(dev_t * dev,unsigned
baseminor,unsigned count,const char *
name);//动态分配
2、分配struce cdev的空间,并用file_operations初始化
void cdev_init(struct cdev * cdev,const struct
file_operations * fops);
3、将设备添加到系统中
int cdev_add(struct cdev *p,dev_t dev,unsigned
count);
从以后的实际的需求分析,我们可以看出内核必须要管理两个东西,1、设备号的管理,2、设备的管理即cdev
那我们就来看内核是如何实现的。
先看内核是如何实现设备号的管理的:
在fs/char_dev.c中:
static struct char_device_struct {
53 struct char_device_struct *next;
//连接同一散列行中的所有散列元素
54 unsigned int major; //主设备号
55 unsigned int baseminor;
//最小的从设备号
56 int minorct; //从设备号的个数
57 char name[64];
58 struct cdev *cdev;
即以后的内核将不要这个结构体成员了。
59 }
*chrdevs[CHRDEV_MAJOR_HASH_SIZE];
在管理设备号的时候,其用的是hash表来实现的。 CHRDEV_MAJOR_HASH_SIZE一般为255,我们找 chrdevs数组用的就是通过其主设备号major,用major%
CHRDEV_MAJOR_HASH_SIZE,来进行索引,对于大于CHRDEV_MAJOR_HASH_SIZE的部分其是通过
chrdevs的next指针串起来的。
这样在进行设备号分配的时候就通过查询该表即可。
值得注意的是该数据结构是字符设备特有的。
设备的管理。
在这里字符设备和块设备都是通过同一个数据结构进行管理的。
在drivers/base/map.c中:
9 struct kobj_map {
20 struct probe {
21 struct probe *next;
//将同一散列行中的元素串起来
22 dev_t dev; //设备号
23 unsigned long range; //从设备号的个数
24 struct module *owner;
//指向提供设备驱动程序的模块
25 kobj_probe_t *get;
//获取与设备关联的kobject实例
26 int (*lock)(dev_t, void *);
27 void *data; //对于字符设备指向struct cdev的一个实例,对于块设备,指向struct genhd的实例
28 } *probes[255];
29 struct mutex *lock;
30 };
31 该数据结构也是通过hash表的算法来进行管理的,即主设备号major%5来进行在该数据库中进行索引。
在通过cdev_init初始化struct cdev的实例后,其调用cdev_add把struct cdev添加到该数据库内。
第二节:进程是如何和文件进行挂钩的。
待续
第三节: 设备文件的系统调用open,read,wirte等,是如何调用到特定于设备的file_operations的。
待续