以前的字符设备驱动框架
0、确定主设备号
1、构造file_opeartions
2、register_chrdev(主设备号, name,file_opeartions )
3、入口函数,调用register_chrdev
4、出口函数
缺点:只能有255个字符设备驱动
很多书里面已经建议不用这种方式了
以前的想法:在虚拟文件系统VFS中,调用sys_open,然后以主设备号为下标,在chrdevs里面找到之前注册的file_operation
现在的想法:以主设备号和次设备号来找到file_operation
major = register_chrdev(0, “hello”, &hello_fops);
本来是(主,0)~(主,255),都对应file_opeartions,霸占了255次设备号;
改成:
将其展开:
①:register_chrdev_region/alloc_chrdev_region
region :区域
从(主,次)到(主,次 + n)都对应该file_opeartions结构体
②:cdev_init
③:cdev_add
这样一来理论上可以支持255 * 255个字符设备
其实只不过是将原来的 register_chrdev 拆分成为上面三个点而已;
参考函数:
linux-2.6.22.6\drivers\char\Scx200_gpio.c
static int __init scx200_gpio_init(void)
{
int rc;
dev_t devid;
if (!scx200_gpio_present()) {
printk(KERN_ERR DRVNAME ": no SCx200 gpio present\n");
return -ENODEV;
}
/* support dev_dbg() with pdev->dev */
pdev = platform_device_alloc(DRVNAME, 0);
if (!pdev)
return -ENOMEM;
rc = platform_device_add(pdev);
if (rc)
goto undo_malloc;
/* nsc_gpio uses dev_dbg(), so needs this */
scx200_gpio_ops.dev = &pdev->dev;
if (major) {
devid = MKDEV(major, 0);
rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio");
} else {
rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio");
major = MAJOR(devid);
}
if (rc < 0) {
dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
goto undo_platform_device_add;
}
cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops);
cdev_add(&scx200_gpio_cdev, devid, MAX_PINS);
return 0; /* succeed */
undo_platform_device_add:
platform_device_del(pdev);
undo_malloc:
platform_device_put(pdev);
return rc;
}
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);
}
分析
如果没有主设备号的话,就创建主设备号;
MKDEV(major, 0) 与 register_chrdev_region(devid, 2, “hello”) 表明(major ,0~1) 对应 hello_fops
如果MKDEV(major, 0);中的0改为1的话, register_chrdev_region(devid, 2, “hello”)不变。就是(major ,1~2) 对应 hello_fops
cdev_init(&hello_cdev, &hello_fops);
cdev_add(&hello_cdev, devid, HELLO_CNT);
分析:创建cdev,和添加cdev;