1.编写驱动程序的第一部就是定义驱动程序为用户提供的能力(机制);
2.举例在计算机内存之上实现若干设备抽象:
scull:simple character Utility for Loading Localities, 区域装载的简单字符工具
scull的源代码实现了以下设备
scull0 ~ scull3
这四个设备分别由一个全局且持久的内存区域组成
scullpipe0 ~ scullpipe3
这四个设备与管道类似,一个进程的读取由另一个进程写入的数据
scullsingle
一次只允许一个进程使用该驱动程序
scullpriv
对于每个虚拟控制台是私有的
sculluid scullwuid
只能由一个用户打开
3.主设备号和次设备号
对字符设备的访问是通过文件系统内的设备名进行的,那些名称被称为特殊文件,设备文件或者简单称之为文件系统数树的节点。他们统称位于/dev目录,字符设备驱动程序的设备文件可通过
命令输出的第一列中的”c“来标识
- crw-rw-rw- 1 root root 1, 5 4月 16 12:59 zero
1:主设备号
标识对应的驱动程序(现代的linux内核允许多个驱动程序共享主设备号)
5:次设备号
由内核使用,用于正确确定设备文件所指的设备
4.设备编号的内部表达
在内核中dev_t()用来保存一个设备号,dev_t是一个32位整数,用前12位代表主设备号,后20位代表次设备号。我们的代码不应该对设备编号的组织做任何假定,应该始终使用定义的宏:
- MAJOR(dev_t dev);//主设备号
- MINOR(dev_t dev);//次设备号
相反,如果将主设备号和次设备号转换成dev_t类型,则使用:
- MKDEV(int major, int minor);
5.分配和释放设备编号
获得一个指定的设备号
- int register_chrdev_region(dev_t first,
- unsigned int count,
- char *name);
first 是要分配的设备好的起始位置
count 是请求连续设备编号的个数
name 是和该编号范围关联的设备名称,它将出现在/proc/devices和sysfs中
动态分配设备号
- int alloc_chrdev_region(dev_t *dev,
- unsigned int firstminor,
- unsigned int count,
- char *name);
dev: 仅用于输出的参数
firstminor: 要使用的被请求的第一个次设备号
count 是请求连续设备编号的个数
name 是和该编号范围关联的设备名称,它将出现在/proc/devices和sysfs中
释放设备号
- void unregister_chrdev_region(dev_t first,
- unsigned int count);
first: 要释放的设备号的起始位置
count: 是释放连续设备编号的个数
6.动态分配主设备号
- if (scull_major) {
- dev = MKDEV(scull_major, scull_minor);
- result = register_chrdev_region(dev, scull_nr_dev, "scull");
- } else {
- result = alloc_chrdev_region(&dev, scull_minor, scull_nr_dev, "scull");
- scull_major = MAJOR(dev);
- }
- if (result < 0) {
- printk(KERN_WARNING "scull: can't get major %d\n", scull_major);
- return result;
- }
-----------------------------未完待续------------------------------
阅读(1069) | 评论(1) | 转发(0) |