下面是一个简单的实例,可以看到驱动是怎样把自定义的open方法和主设备号对应起来的
#include <linux/module.h> /*它定义了模块的 API、类型和宏(MODULE_LICENSE、MODULE_AUTHOR等等),所有的内核模块都必须包含这个头文件。*/ #include <linux/init.h> #include <linux/fs.h> //设备号相关函数 #include <linux/slab.h> //内存分配相关函数 #include <linux/types.h> #include <linux/kdev_t.h>//设备号相关函数 #include <linux/cdev.h>//字符设备头文件 #include <linux/module.h> struct char_dev { int size; char *data; struct cdev cdev;//内核中的字符设备 }; int major = 0; int minor = 0; struct char_dev char_devices; int char_open(struct inode *inode, struct file *filep) { int Major = 0; Major = MAJOR(inode->i_rdev); printk("open my_char_dev major: %d\n", Major); return 0; } struct file_operations char_fops = { .owner = THIS_MODULE, .open = char_open, }; static void char_exit(void) //如果init函数中调用了该函数,则不应有 __exit { dev_t dev; printk("char device driver exit \n"); //释放设备号 dev = MKDEV(major, minor); unregister_chrdev_region(dev, 1); printk("release major %d\n", major); //释放内存 if(char_devices.data){ kfree(char_devices.data); } //从内核中删除字符设备 cdev_del(&(char_devices.cdev)); } static int __init char_init(void)//__init一个标记,表明是初始化函数 { //初始化的代码 dev_t dev; int result; printk("char device driver init \n"); //动态向内核申请设备号 result = alloc_chrdev_region(&dev, 0, 1, "my_char_dev"); major = MAJOR(dev); minor = MINOR(dev); printk("alloc major %d\n", major); if (result < 0) { printk(KERN_WARNING "my_char_dev: can't get major %d\n", major); return result; } //为设备分配一块内存 char_devices.size = 100; char_devices.data = (char*)kmalloc(char_devices.size, GFP_KERNEL); if (!char_devices.data) { result = -ENOMEM; goto fail; //不能直接退出函数,需要释放设备号 } //向内核中添加字符设备cdev cdev_init(&(char_devices.cdev), &char_fops); char_devices.cdev.owner = THIS_MODULE; char_devices.cdev.ops = &char_fops; result = cdev_add(&(char_devices.cdev), dev, 1); if((result < 0)) { printk(KERN_WARNING "Error %d adding my_char_dev\n", result); goto fail; } return 0; //成功 fail: char_exit(); return result; } MODULE_LICENSE("Dual BSD/GPL"); //当模块被加载时,执行moudle_init函数,该函数会调用初始化函数 module_init(char_init); //模块卸载时,调用,释放资源 module_exit(char_exit);
注:驱动insmod后,通过/proc/devices查看主设备号,然后通过mknod在/dev下创建设备节点,注意保持主设备好的一致,当前的节点只支持open方法,可以在demsg中进行验证。