加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

linux驱动的实现揭秘之如何从用户态调用到内核态:一

(2013-12-22 14:49:25)
标签:

it

分类: 毅哥分析linux设备驱动

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的部分其是通过 chrdevsnext指针串起来的。

这样在进行设备号分配的时候就通过查询该表即可。

值得注意的是该数据结构是字符设备特有的。


设备的管理。

在这里字符设备和块设备都是通过同一个数据结构进行管理的。

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_addstruct cdev添加到该数据库内。

 

第二节:进程是如何和文件进行挂钩的。

待续

第三节: 设备文件的系统调用open,read,wirte等,是如何调用到特定于设备的file_operations的。

待续

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有