设备名
字符设备通过文件系统中的文件名(设备名)来访问.
这些设备名, 文件名有许多不同的, 可以互换的叫法, 比如: 设备节点, 节点文件, 设备文件... 在Linux中, 所有的设备都被视为特殊文件. 它们储存在文件系统中, 但是仅占用文件目录, 而不涉及存储数据. 实际上, 它们只记录了设备所属的设备类别, 主设备号和从设备号等相关信息.
上述的设备名位于/dev目录中, 可以通过ls -l 命令来查看它们:
$ ls -l sda[1-3]
显示下列信息:
brw-rw---- 1 root disk 8, 1 2006-06-14 20:26 /dev/sda1
brw-rw---- 1 root disk 8, 2 2006-06-14 20:26 /dev/sda2
brw-rw---- 1 root disk 8, 3 2006-06-14 12:30 /dev/sda3
上述的命令列出了系统中SCSI硬盘的信息. 注意这些内容与列出一般文件的区别:
(1) 开头是b, 表示是块文件(本章讨论的是char设备, 自然以c开头)
(2) 对于设备文件, 在最终修改时间之前列出的是以逗号分隔的两个数字, 而不是一般文件的文件大小.
主, 从设备号
Linux利用设备号来标识设备文件, 设备号分为主设备号和从设备号. 上述的逗号分隔的两个数字就分别是主设备号和从设备号.
主设备号: 标识设备对应的驱动程序. 每个在内核中的设备驱动程序(包括编译进内核的和动态加载的)都有一个唯一的主设备号对应, 内核根据主设备号将设备和相应的设备驱动程序对应起来.
从设备号: 内核使用从设备号来区分具体的物理设备. 实际上, 次设备号只有设备驱动程序使用, 内核的其它部分对它一无所知: 从设备号只是用在驱动程序中来指示某个物理设备.
不同类型的设备文件, 其设备号是独立的. 关于设备号的分配, 可参考内核源码树的 Documentation/devices.txt.
设备号的内部表征
2.6以前的内核将主, 从设备号限定在255以内, 2.6的内核没有了这一限制.
在2.6.0及以后版的内核中, 主, 从设备号位于一个dev_t类型的32位数中. (dev_t位于/usr/include/linux/types.h中). 前12位用于主设备号, 后20位用于从设备号. 但这一约定可能会随着版本的更新而改变, 所以在获取主,从设备号时, 不要对dev_t类型的组织作任何假设, 而应使用这两个宏:
MAJOR(dev_t dev);
MINOR(dev_t dev);
同样, 使用下面的宏来将主, 从设备号转化为一个设备:
MKDEV(int major, int minor);
上述宏位于 /usr/include/linux/kdev_t.h中.
分配, 释放设备号
向系统增加一个驱动程序时, 首先要赋予它设备号. 一旦设备注册到内核表中, 无论何时操作与设备驱动程序的主设备号匹配的设备文件, 内核都会调用驱动程序中的函数.
分配设备号:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
返回: 0 if 成功分配. 负数 if 失败.
first : 你想要分配的第一个设备号, 一般它的从设备号为0.
count: 分配设备号(分配的设备号为连续的)个数.
name: 用来与设备号对应的设备名, 它位于/proc/devices和sysfs中.
register_chrdev_region适用于你预先知道需要分配哪个设备号的情况. 然而一般来说, 你无法提前知道设备将使用那个主设备号. 这种情况下就应该使用下面的函数:
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
返回: 0 if 成功分配. 负数 if 失败.
在该函数中, count 和 name与前面的函数相同.
*dev : 输出成功分配的设备号中的第一个设备号.
firstminor : 分配的第一个从设备号, 一般为0.
分配设备号有两种选择, 但释放设备号只能调用下面的函数:
void unregister_chrdev_region(dev_t first, unsigned int count);
count于前两个函数中的count都是相同的, first与dev_t first相同, 但和dev_t *dev是如何对应的呢?
一般在模块的清理函数中调用它.
动态分配主设备号
有两个选择来分配主设备号:
静态地, 即直接使用内核源码数的Documentation/devices.txt中定义的未使用的主设备号. 它对应于register_chrdev_region函数.
动态地: 即动态分配一个主设备号.它对应于alloc_chrdev_region函数. 推荐使用动态分配的方法, 这样你就能在加载甚至编译模块的时候设定主设备号.
动态分配有个缺点: 你无法在分配设备号之前创造设备节点. 但一旦设备号被分配之后, 你可以通过/proc/devices来读取它. 你还可以通过sysfs来获取更多的设备信息. 2.6版内核的sysfs被挂载到/sys目录.
字符设备通过文件系统中的文件名(设备名)来访问.
这些设备名, 文件名有许多不同的, 可以互换的叫法, 比如: 设备节点, 节点文件, 设备文件... 在Linux中, 所有的设备都被视为特殊文件. 它们储存在文件系统中, 但是仅占用文件目录, 而不涉及存储数据. 实际上, 它们只记录了设备所属的设备类别, 主设备号和从设备号等相关信息.
上述的设备名位于/dev目录中, 可以通过ls -l 命令来查看它们:
$ ls -l sda[1-3]
显示下列信息:
brw-rw---- 1 root disk 8, 1 2006-06-14 20:26 /dev/sda1
brw-rw---- 1 root disk 8, 2 2006-06-14 20:26 /dev/sda2
brw-rw---- 1 root disk 8, 3 2006-06-14 12:30 /dev/sda3
上述的命令列出了系统中SCSI硬盘的信息. 注意这些内容与列出一般文件的区别:
(1) 开头是b, 表示是块文件(本章讨论的是char设备, 自然以c开头)
(2) 对于设备文件, 在最终修改时间之前列出的是以逗号分隔的两个数字, 而不是一般文件的文件大小.
主, 从设备号
Linux利用设备号来标识设备文件, 设备号分为主设备号和从设备号. 上述的逗号分隔的两个数字就分别是主设备号和从设备号.
主设备号: 标识设备对应的驱动程序. 每个在内核中的设备驱动程序(包括编译进内核的和动态加载的)都有一个唯一的主设备号对应, 内核根据主设备号将设备和相应的设备驱动程序对应起来.
从设备号: 内核使用从设备号来区分具体的物理设备. 实际上, 次设备号只有设备驱动程序使用, 内核的其它部分对它一无所知: 从设备号只是用在驱动程序中来指示某个物理设备.
不同类型的设备文件, 其设备号是独立的. 关于设备号的分配, 可参考内核源码树的 Documentation/devices.txt.
设备号的内部表征
2.6以前的内核将主, 从设备号限定在255以内, 2.6的内核没有了这一限制.
在2.6.0及以后版的内核中, 主, 从设备号位于一个dev_t类型的32位数中. (dev_t位于/usr/include/linux/types.h中). 前12位用于主设备号, 后20位用于从设备号. 但这一约定可能会随着版本的更新而改变, 所以在获取主,从设备号时, 不要对dev_t类型的组织作任何假设, 而应使用这两个宏:
MAJOR(dev_t dev);
MINOR(dev_t dev);
同样, 使用下面的宏来将主, 从设备号转化为一个设备:
MKDEV(int major, int minor);
上述宏位于 /usr/include/linux/kdev_t.h中.
分配, 释放设备号
向系统增加一个驱动程序时, 首先要赋予它设备号. 一旦设备注册到内核表中, 无论何时操作与设备驱动程序的主设备号匹配的设备文件, 内核都会调用驱动程序中的函数.
分配设备号:
int register_chrdev_region(dev_t first, unsigned int count, char *name);
返回: 0 if 成功分配. 负数 if 失败.
first : 你想要分配的第一个设备号, 一般它的从设备号为0.
count: 分配设备号(分配的设备号为连续的)个数.
name: 用来与设备号对应的设备名, 它位于/proc/devices和sysfs中.
register_chrdev_region适用于你预先知道需要分配哪个设备号的情况. 然而一般来说, 你无法提前知道设备将使用那个主设备号. 这种情况下就应该使用下面的函数:
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
返回: 0 if 成功分配. 负数 if 失败.
在该函数中, count 和 name与前面的函数相同.
*dev : 输出成功分配的设备号中的第一个设备号.
firstminor : 分配的第一个从设备号, 一般为0.
分配设备号有两种选择, 但释放设备号只能调用下面的函数:
void unregister_chrdev_region(dev_t first, unsigned int count);
count于前两个函数中的count都是相同的, first与dev_t first相同, 但和dev_t *dev是如何对应的呢?
一般在模块的清理函数中调用它.
动态分配主设备号
有两个选择来分配主设备号:
静态地, 即直接使用内核源码数的Documentation/devices.txt中定义的未使用的主设备号. 它对应于register_chrdev_region函数.
动态地: 即动态分配一个主设备号.它对应于alloc_chrdev_region函数. 推荐使用动态分配的方法, 这样你就能在加载甚至编译模块的时候设定主设备号.
动态分配有个缺点: 你无法在分配设备号之前创造设备节点. 但一旦设备号被分配之后, 你可以通过/proc/devices来读取它. 你还可以通过sysfs来获取更多的设备信息. 2.6版内核的sysfs被挂载到/sys目录.