第3章 字符设备驱动程序(1)

1. 主设备号和次设备号

主设备号标识设备对应的驱动程序,内核利用主设备号在open操作中将设备与相应的驱动程序对应起来。次设备号只是由那些主设备号已经确定的驱动程序使用,内核的其它部分不会用到它,而仅是把它传递给驱动程序。一个驱动程序控制多个设备是常有的事情(如上面的例子所示) ,而次设备号为驱动程序提供了一种区分不同设备的方法。

在内核中, dev_t 类型(在 <linux/types.h>中定义)用来持有设备编号 -- 主次部分都包括. 对于 2.6.0 内核, dev_t 是 32 位的量, 12 位用作主编号, 20 位用作次编号. 你的代码应当, 当然, 对于设备编号的内部组织从不做任何假设; 相反, 应当利用在 <linux/kdev_t.h>中的一套宏定义. 为获得一个 dev_t 的主或者次编号, 使用:

  1. MAJOR(dev_t dev);  
  2. MINOR(dev_t dev); 

相反, 如果你有主次编号, 需要将其转换为一个 dev_t, 使用:

  1. MKDEV(int major, int minor);  

在建立一个字符驱动时你的驱动需要做的第一件事是获取一个或多个设备编号来使用. 为此目的的必要的函数是 register_chrdev_region, 在 <linux/fs.h>中声明:

  1. int register_chrdev_region(dev_t first, unsigned int count, char *name);  

first 是你要分配的起始设备编号. first 的次编号部分常常是 0; count 是你请求的连续设备编号的总数. 注意, 如果 count 太大, 你要求的范围可能溢出到下一个主编号; 最后, name 是应当连接到这个编号范围的设备的名子; 它会出现在 /proc/devices 和 sysfs 中.如果分配成功进行, register_chrdev_region 的返回值是 0. 出错的情况下, 返回一个负的错误码, 你不能存取请求的区域.

如果你确实事先知道你需要哪个设备编号, register_chrdev_region 工作得好. 然而, 你常常不会知道你的设备使用哪个主编号; 在 Linux 内核开发社团中一直努力使用动态分配设备编号. 内核会乐于动态为你分配一个主编号, 但是你必须使用一个不同的函数来请求这个分配.

  1. int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, 
  2.                                unsigned int count, char *name);  

使用这个函数,dev是一个output-only参数,它在函数成功完成时hold你的分配范围的第一个数,firstminor是请求的第一个次编号,它常常是0.count 和 name参数如request_chrdev_region一样。

 

设备编号的释放使用:

void unregister_chrdev_region(dev_t first, unsigned int count);

调用 unregister_chrdev_region 的地方常常是你的模块的 cleanup 函数.

 

对于新驱动, 我们强烈建议你使用动态分配来获取你的主设备编号, 而不是随机选取一个当前空闲的编号. 换句话说, 你的驱动应当几乎肯定地使用 alloc_chrdev_region, 不是 register_chrdev_region.

动态分配的缺点是你无法提前创建设备节点, 因为分配给你的模块的主编号会变化. 对于驱动的正常使用, 这不是问题, 因为一旦编号分配了, 你可从 /proc/devices 中读取它.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值