每个字符设备通过<主设备号> <次设备号>来标识,操作一个device就是通过主,次设备号对应到driver中的operation的
一个字符设备可以对应多个次设备号,比如(major,x)~(major,x+n)都对应同一个设备,即同一套file_operations
#if 0
major = register_chrdev(0, "hello", &hello_fops); /* (major, 0), (major, 1), ..., (major, 255)都对应hello_fops */
#else
if (major) {
devid = MKDEV(major, 0);
register_chrdev_region(devid, HELLO_CNT, "hello"); /* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */
} else {
alloc_chrdev_region(&devid, 0, HELLO_CNT, "hello"); /* (major,0~1) 对应 hello_fops, (major, 2~255)都不对应hello_fops */
major = MAJOR(devid);
}
cdev_init(&hello_cdev, &hello_fops);
cdev_add(&hello_cdev, devid, HELLO_CNT);
#endif
【手动创建设备结点】
操作一个设备结点,就是通过主,次设备号跟driver匹配起来,从而操作到相应的驱动中的操作函数(file_operation)
cat /proc/devices来查看现在支持的所有设备,包含主设备号,次设备号,名字
mknod /dev/xxx c <主设备号> <次设备号> 来创建设备结点,这个设备结点对应于某个特定的设备
我们可以看出,一个字符设备驱动可以对应多个设备结点(一个字符设备可以对应多个次设备号)
【自动创建设备结点】
1)创建类(可动态创建也可以静态创建)
2)基于这个类创建设备(可动态创建也可以静态创建)
3) udev根据/sys/class/下的设备在/dev/下动态创建设备结点(前提是dev.devt有赋值,例如vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);)
4) /sys/class/下的目录是根据class.name来确定的,例如,对与video来说就是/sys/class/video4linux/videoX
i2c_dev_class = class_create(THIS_MODULE, "i2c-dev");<span> </span>//动态创建
i2c_dev->dev = device_create(i2c_dev_class, &adap->dev,
MKDEV(I2C_MAJOR, adap->nr), NULL,
"i2c-%d", adap->nr);
if (IS_ERR(i2c_dev->dev)) {
res = PTR_ERR(i2c_dev->dev);
goto error;
}
res = device_create_file(i2c_dev->dev, &dev_attr_name);
static struct class video_class = { //静态创建
.name = VIDEO_NAME,
.dev_attrs = video_device_attrs,
};
/* Part 4: register the device with sysfs */
vdev->dev.class = &video_class;
vdev->dev.devt = MKDEV(VIDEO_MAJOR, vdev->minor);
if (vdev->parent)
vdev->dev.parent = vdev->parent;
dev_set_name(&vdev->dev, "%s%d", name_base, vdev->num);
ret = device_register(&vdev->dev);
cls = class_create(THIS_MODULE, "hello"); //在sys目录下创建hello类
class_device_create(cls, NULL, MKDEV(major, 0), NULL, "hello0");//在hello类上创建hello0设备,mdev会自动创建/dev/hello0结点与之对应
class_device_create(cls, NULL, MKDEV(major, 1), NULL, "hello1"); * /dev/hello1 */
class_device_create(cls, NULL, MKDEV(major, 2), NULL, "hello2"); /* /dev/hello2 */
static struct class video_class = {
//静态创建
.name = VIDEO_NAME,
.dev_attrs = video_device_attrs,
};
.name = VIDEO_NAME,
.dev_attrs = video_device_attrs,
};