我是一名初学者,对于与设备驱动程序相关的主要号码和次要号码有一些了解。我知道大多数可以插入Linux系统的设备都有一个主要号码。并且基于这个主要号码,相应的驱动程序会被加载。
我有这个疑问,请告诉我内核如何从设备中读取主要号码,当它被插入时?
请尽可能简单地解释从设备插入到驱动程序加载的步骤。
先行致谢。
我有这个疑问,请告诉我内核如何从设备中读取主要号码,当它被插入时?
请尽可能简单地解释从设备插入到驱动程序加载的步骤。
先行致谢。
主/次号适用于块设备和字符设备。
你不能从设备中“检测”出一个主号。也许你认为USB设备可以通信设备号码,Linux使用这些号码,但USB供应商/产品ID与主要号码无关。如果你将一个完全愚笨的串行设备插入串口,内核无法知道你插入/拔下了什么。
因此,例如,如果你想要一个字符设备的主号,那么要么你使用
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count, char *name);
像NKamrath所说的那样,或者您可以使用绝对路径。但要注意,许多已被保留。
据我所知,这里是您所要求的步骤:
register_chrdev_region
)一个主设备号,如果它已经被保留了(请参阅这个著名的保留列表);否则,它会请求内核为其分配一个(例如alloc_chrdev_region
);驱动程序还将为该驱动程序保留一个次设备区域。此时,您可以使用该驱动程序的设备号进行通信,但是如何呢?在/dev
中还没有任何内容……一种方法是在您知道要进行通信的主/次设备号对时使用mknod
。您会发出:
# mknod /dev/mydevice c 232 4
这是要求:请在路径/dev/mydevice
下创建一个设备节点,它与主设备号为232、次设备号为4的字符(c
)设备相连。但是你怎么知道这些数字呢?它们可能是绝对值(保留列表),或者驱动程序printk
输出它们以使您可以手动完成。
这里有更好的方法。
仍然在设备驱动程序的初始化函数中:驱动程序将设备注册为Sysfs设备(请参阅device_create
)。这将把设备放入/sys
树中,其节点(一个目录)将具有名为uevent
的文件。如果您运行cat
命令,它将输出类似以下内容:
MAJOR=232
MINOR=4
DEVNAME=whatever
试一试:
$ cat /sys/class/tty/console/uevent
是否匹配
$ ls -l /dev/console
现在,udev 是负责管理/dev
的用户空间程序。总体而言,它简单地扫描/sys
树来自动填充/dev
。您还可以像这样查看所有字符和块设备的主/次编号:
$ ls /sys/dev/char
$ ls /sys/dev/block
大概就是这样了。如果你想更好地理解这一切,可以开发一个虚拟驱动程序,尝试让它自动出现在/dev
中。
int register_chrdev_region(dev_t first, unsigned int count);
int alloc_chrdev_region(dev_t *dev, unsigned int firstminor, unsigned int count,
char *name);
要读取主要编号,请使用
int MAJOR(dev_t dev);
insmod
命令。然后,内核尝试使用您给出的编号,或者如果您使用了alloc函数,则动态分配一个空闲主编号。正确解释内核和驱动程序设计的内部工作需要大量的解释。但是,有一本非常好的免费书籍(对于编程书籍来说)叫做《Linux Device Drivers 3rd Edition》,它很容易阅读,可以为驱动程序提供很好的介绍,即使您只阅读前三章(大约100页),您也将对我认为您正在查找的内容有所了解。此外,所有示例的源代码都可用,因此您可以修改其演示文稿并更快地开始编写驱动程序!