在Linux下,字符设备和块设备都体现了“一切皆为文件”的思想,对于这两种设备而言,他们在Linux系统中都有一个对应的文件来“代表”它们的存在,那就是设备文件。应用程序通过操作某个设备文件,便可以操作对应的硬件。设备有主设备号和次设备号,例如在Linux下通过ls -l /dev/ttyS0命令可以看到如图信息字符设备设备节点创建的两种方法_字符设备驱动

对于/dev/ttyS0设备文件,c表示它是一个字符设备文件(如果是'b'则是块设备文件),4是它的主设备号,64是它的次设备号。Linux系统根据设备文件的类型可以知道它是字符设备还是块设备,通过主设备号就可以找到它在内核中注册的file_operations结构,而次设备号是驱动程序本身用来区分它是同类设备中低第几个,也就是说相同的主设备号表示同一类设备,次设备号则用来区分这类设备中的哪一个。

    在写驱动程序时,一般在初始化函数中利用register_chrdev()函数向内核注册设备号:

int register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)

major是指定的主设备号(必须是可用并且系统未使用的),如果这个参数设为0,则表示由系统分配,为了避免冲突的麻烦,一般都设为0,由系统分配,再定义一个变量来接受这个函数的返回值得到主设备号;name代表名字 可以任意取;fops是要注册的file_operatios结构体指针;这样就完成了注册。同样,在卸载函数中则要用 int unregister_chrdev(unsigned int major, const char *name)函数去卸载。例如:字符设备设备节点创建的两种方法_字符设备驱动_02

以上只是向内核注册了该驱动程序的file_operations结构体和设备号,在挂载驱动程序时依然没有创建对应的设备文件。在创建设备文件之前,首先通过cat /proc/devices命令查看是否已经创建好“led”设备节点,并查看其主设备号。创建设备文件的方法有两种:

  1. 手工创建:就是在挂载驱动程序之后,根据led的主设备号(假设是252)通过命令创建,如:mknod /dev/leds  c 252 1 创建,此时在/dev下就有一个对应设备文件字符设备设备节点创建的两种方法_字符设备驱动_03

  2. 在加载驱动程序时自动创建:Linux内核提供了一组函数,可以在模块加载时自动在/dev目录下创建相对应的设备节点,并在卸载模块时删除该节点,能实现这样操作的前提是用户空间已经移植了udev(简化版本的mdev)。相关的函数和结构:(1)struct class,是一个设备结构体,注册一个类结构,会在/sys/class目录下创建对应的文件夹,文件夹中保存有在/dev目录下自动生成设备节点的信息。(2)struct class_device结构体。创建使用如图

    字符设备设备节点创建的两种方法_字符设备驱动_04

  3. 这样在挂载成功驱动程序之后,在/sys/class下就产生了一个led文件夹,里面有一个leds文件的包含信息;并且已经自动在/dev目录下创建好了leds字符设备文件,不用手动创建。

  4. 相比之下,一般使用第二种方法更加简便,也适合使用。