linux驱动开发 主设备号与次设备号

发布时间:2016-12-10 22:55:01 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"linux驱动开发 主设备号与次设备号",主要涉及到linux驱动开发 主设备号与次设备号方面的内容,对于linux驱动开发 主设备号与次设备号感兴趣的同学可以参考一下。

一个字符设备或者块设备都有一个主设备号和次设备号。 主设备号和次设备号统称为设备号。主设备号用来表示一个特定的驱动程序。次设备号用来表示使用该驱动程序的各个 设备。例如一个嵌入式系统,有两个LED指示灯,LED灯需要独立的打开或者关闭。那么 ,可以写一个LED灯的字符设备驱动程序,可以将其主设备号注册成5号设备,次设备号 分别为1和2。这里,次设备号就分别表示两个LED灯。 1.主设备号和次设备号的表示 在Linux内核中,dev_t类型用来表示设备号。在Linux 2.6.29.4中,dev_t定义为一个 无符号长整型变量,如下:typedef u_long dev_t; u_long在32位机中是4个字节,在64位机中是8字节。以32位机为例,其中高12表示主设备号,低20为表示次设备号,如图6.1所示。 2.主设备号和次设备号的获取 为了写出可移植的驱动程序,不能假定主设备号和次设备号的位数。不同的机型中,主 设备号和次设备号的位数可能是不同的。应该使用MAJOR宏得到主设备号,使用MINOR宏来得到次设备号。下面是两个宏的定义: #define MINORBITS   20                                  /*次设备号位数*/ #define MINORMASK   ((1U << MINORBITS) - 1)             /*次设备号掩码*/ #define MAJOR(dev)  ((unsigned int) ((dev) >> MINORBITS)) /*dev右移20位得到主设备号*/  #define MINOR(dev)((unsigned int) ((dev) & MINORMASK))    /*与次设备掩码与,得到次设备号*/ MAJOR宏将dev_t向右移动20位,得到主设备号;MINOR宏将dev_t的高12位清零,得到次 设备号。相反,可以将主设备号和次设备号转换为设备号类型(dev_t),使用宏 MKDEV可以完成这个功能。#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))   MKDEV宏将主设备号(ma)左移20位,然后与次设备号(mi)相与,得到设备号。 3.静态分配设备号 静态分配设备号,就是驱动程序开发者,静态地指定一个设备号。对于一部分常用的设 备,内核开发者已经为其分配了设备号。这些设备号可以在内核源码documentation/ devices.txt文件中找到。如果只有开发者自己使用这些设备驱动程序,那么其可以选 择一个尚未使用的设备号。在不添加新硬件的时候,这种方式不会产生设备号冲突。但 是当添加新硬件时,则很可能造成设备号冲突,影响设备的使用。 4.动态分配设备号 由于静态分配设备号存在冲突的问题,所以内核社区建议开发者使用动态分配设备号的 方法。动态分配设备号的函数是alloc_chrdev_region()。 5.查看设备号 当静态分配设备号时,需要查看系统中已经存在的设备号,从而决定使用哪个新设备号 。可以读取/proc/devices文件获得设备的设备号。/proc/devices文件包含字符设备和 块设备的设备号,如下所示。[[email protected] /]# cat /proc/devices /*cat命令查看 /proc/devices文件的内容*/  Character devices:                  /*字符设备*/ 1 mem    4 /dev/vc/0    7 vcs    13 input    14 sound    21 sg  Block devices:  /*块设备*/    1 ramdisk    2 fd    8 sd    253  device-mapper    254 mdp    3. 6.1.3 申请和释放设备号  内核维护着一个特殊的数据结构,用来存放设备号与设备的关系。在安装设备时,应该 给设备申请一个设备号,使系统可以明确设备对应的设备号。设备驱动程序中的很多功 能,是通过设备号来操作设备的。下面,首先对申请设备号进行简述。 1.申请设备号 在构建字符设备之前,首先要向系统申请一个或者多个设备号。完成该工作的函数是 register_chrdev_region(),该函数在<fs/char_dev.c>中定义: int register_chrdev_region(dev_t from, unsigned count, const char *name); 其中,from是要分配的设备号范围的起始值。一般只提供from的主设备号,from的次设 备号通常被设置成0。count是需要申请的连续设备号的个数。最后name是和该范围编号 关联的设备名称,该名称不能超过64字节。 和大多数内核函数一样,register_chrdev_region()函数成功时返回0。错误时,返回 一个负的错误码,并且不能为字符设备分配设备号。下面是一个例子代码,其申请了 CS5535_GPIO_COUNT个设备号。retval = register_chrdev_region(dev_id, CS5535_GPIO_COUNT,NAME); 在Linux中有非常多的字符设备,在人为的为字符设备分配设备号时,很可能发生冲突 。Linux内核开发者一直在努力将设备号变为动态的。可以使用 alloc_chrdev_region()函数达到这个目的。 int alloc_chrdev_region(dev_t *dev, unsigned baseminor,unsigned count, const char *name) 在上面的函数中,dev作为输出参数,在函数成功返回后将保存已经分配的设备号。函 数有可能申请一段连续的设备号,这是dev返回第一个设备号。baseminor表示要申请的 第一个次设备号,其通常设为0。count和name与register_chrdev_region()函数的对应 参数一样。count表示要申请的连续设备号个数,name表示设备的名字。下面是一个例 子代码,其申请了CS5535_GPIO_COUNT个设备号。retval = alloc_chrdev_region(&dev_id, 0, CS5535_GPIO_COUNT, NAME); 2.释放设备号 使用上面两种方式申请的设备号,都应该在不使用设备时,释放设备号。设备号的释放 统一使用下面的函数:void unregister_chrdev_region(dev_t from, unsignedcount); 在上面这个函数中,from表示要释放的设备号,count表示从from开始要释放的设备号 个数。通常,在模块的卸载函数中调用unregister_chrdev_region()函数。 转  http://cngeeks.net/forum.php?mod=viewthread&tid=532

上一篇:javascript封装的类似java List类
下一篇:Exercises 3.3 E7

相关文章

相关评论