1.在字符设备驱动模块加载函数中应该实现设备号的申请和cdev 的注册,而在卸载函数中应实现设备号的释放和cdev 的注销。
1//设备结构体 2 struct xxx_dev_t 3 { 4 struct cdev cdev; 5 ... 6 } xxx_dev; 7 //设备驱动模块加载函数 8 static int _ _init xxx_init(void) 9 { 10 ... 11 cdev_init(&xxx_dev.cdev, &xxx_fops); //初始化cdev 12 xxx_dev.cdev.owner = THIS_MODULE; 13 //获取字符设备号 14 if (xxx_major) 15 { 16 register_chrdev_region(xxx_dev_no, 1, DEV_NAME); 17 } 18 else 19 { 20 alloc_chrdev_region(&xxx_dev_no, 0, 1, DEV_NAME); 21 } 22 23 ret = cdev_add(&xxx_dev.cdev, xxx_dev_no, 1); //注册设备 24 ... 25 } 26 /*设备驱动模块卸载函数*/ 27 static void _ _exit xxx_exit(void) 28 { 29 unregister_chrdev_region(xxx_dev_no, 1); //释放占用的设备号 30 cdev_del(&xxx_dev.cdev); //注销设备 31 ... 32 }
2.file_operations 结构体中成员函数是字符设备驱动与内核的接口,是用户空间对Linux 进行系统调用最终的落实者。大多数字符设备驱动会实现read()、write()和ioctl()函数。
1 struct file_operations xxx_fops = 2 { 3 .owner = THIS_MODULE, 4 .read = xxx_read, 5 .write = xxx_write, 6 .ioctl = xxx_ioctl, 7 ... 8 };
下面将基于虚拟的 globalmem 设备进行字符设备驱动的讲解。globalmem 意味着“全局内存”,在globalmem 字符设备驱动中会分配一片大小为GLOBALMEM_ SIZE的内存空
间,并在驱动中提供针对该片内存的读写、控制和定位函数,以供用户空间的进程能通过Linux 系统调用访问这片内存。
时间: 2024-11-07 19:39:25