register_chrdev(unsigned int major, const char *name,const struct file_operations *fops)
major 就是主设备号
name 是驱动名(这个不是设备名)
fops 是file_operations结构体,定义了接口和应用层的函数对接
在2.6内核版本(老版本可能不是这样实现的)中其调用关系
register_chrdev(major,name,fops)
__register_chrdev(major, 0, 256, name, fops);
__register_chrdev_region 申请主设备号为major,次设备号0到256
cdev = cdev_alloc();
cdev->ops = fops;
cdev_add(cdev,MKDEV(主设备号为major,次设备号为0),count) 创建次设备号0到256的驱动
看这接口实现是我们一下创建了主设备为major,次设备号为0到256的驱动,
理论上我们现在可以在dev目录下用mknod命令创建此设备为0到256的设备节点,
但考虑到之前版本不知道是如何实现的这个接口,最安全的做法是在/dev目录下创建主设备号为major此设备号为0 的节点
☆新版本的注册流程
=> register_chrdev_region/alloc_chrdev_region 静态分配1到多个主设备号/动态申请1个主设备号,次设备号可设置范围
=> cdev_alloc(■推荐)分配一个cdev 或者 定义一个cdev
=> 调用cdev_init(■推荐) 或者 赋值方式 把 file_operations结构体关联到 cdev
=> cdev_add(cdev,起始设备号,count)
综合分析 :
==>在新版本的内核(老版本不做考虑和分析)使用新的接口流程,可以更加灵活的控制次设备号,老的注册接口虽然创建了256个此设备号,但是这只是内部实现不保证以后不做修改,也就是如果用老接口我们默认是它的次设备号是只有0
==>当我们想创建好几个主设备一样,N个次设备号的设备节点时,要么我们只创建一个file_operations,然后在read,write等函数里根据次设备不同做不同的操作,或者每个次设备创建一个file_operations,然后每个次设备调用一次cdev_init + cdev_add
☆自动创建设备节点
关于老版本内核手动创建设备节点不做分析。
自动创建设备节点需要调用这两个函数:
struct class * class_create(owner, name) 在/sys/class目录下创建名字为name的目录
struct device *device_create(struct class *class, struct device *parent,dev_t devt, void *drvdata, const char *fmt, ...)
在class类目录下创建设备,
举例 :
struct class *myclass = class_create(THIS_MODULE, “my_device_driver”);
class_device_create(myclass, NULL, MKDEV(major, 0), NULL, “my_device”);
这样驱动加载后udev就会自动在/dev下创建my_device设备文件,设备文件的主设备号为major,此设备号0
class_create
__class_create
__class_register
kset_register
kobject_uevent
device_create
device_create_vargs
kobject_set_name_vargs
device_register
device_add
kobject_add
device_create_file
device_create_sys_dev_entry
devtmpfs_create_node
device_add_class_symlinks
device_add_attrs
device_pm_add
kobject_uevent