cdev结构体
描述字符设备的一个结构体
struct cdev{
struct kobject kobj;
struct module *owner;//属于哪个模块的
const struct file_operations *ops;//文件操作集
struct list_head list;//链表的节点
dev_t dev;//设备号
unsigned int count;//设备号数量
};
步骤
- 完成第十章的文章里的步骤
- 添加头文件
- 定义一个cdev结构体和文件操作集
- 在驱动init函数中获取设备号后使用cdev_init函数初始化cdev结构体成员变量
- void cdev_init(struct cdev* , const struct file_operations *);
- 参数1:要初始化的cdev
- 参数2:文件操作集,在函数中会将操作集赋值到cdev -> ops
- 在驱动init函数中初始化cdev结构体后使用cdev_add函数注册字符设备到内核
- int cdev_add(struct cdev* ,dev_t,unsigned);
- 参数1:cdev 的结构体指针
- 参数2:设备号
- 参数3:次设备号的数量
- 在驱动exit函数中释放设备号后使用cdev_del函数注销字符设备
- void cdev_del(struct cdev *);
- 参数1:cdev 的结构体指针
- 如果要测试的话就在文件操作集中定义open函数,在open函数中输出一句话,等后面拿来测试是否成功
例子
- 在第十章的基础上添加后面几个步骤
- 编辑驱动.c
#include <linux/init.h> #include <linux/module.h> #include <linux/miscdevice.h> #include <linux/fs.h> #include <linux/kdev_t.h> #include <linux/uaccess.h> #include <linux/cdev.h> #define DEVICE_NUMBER 1 #define DEVICE_SNAME "schrdev" #define DEVICE_ANAME "achrdev" #define DEVICE_MINOR_NUMBER 0 static int major_num,minor_num; module_param(major_num,int,S_IRUSR); module_param(minor_num,int,S_IRUSR); struct cdev cdev; module_init(misc_init); module_exit(misc_exit); int chrdev_open(struct inode * inode,struct file * file) { printk("hello misc_open\n"); return 0; } struct file_operations chrdev_ops={ .owner = THIS_MODULE, .open = chrdev_open }; static int misc_init(void) { dev_t dev_num; int ret; if(major_num) { printk("major_num= %d\n",major_num); printk("minor_num= %d\n",minor_num); dev_num = MKDEV(major_num,minor_num); ret = register_chrdev_region(dev_num,DEVICE_NUMBER ,DEVICE_SNAME ); if(ret<0) { printk("register_chrdev_region error\n"); } printk("register_chrdev_region ok\n"); } else { ret = alloc_chrdev_region(&dev_num,DEVICE_MINOR_NUMBER,DEVICE_NUMBER,DEVICE_ANAME); if(ret<0) { printk("alloc_chrdev_regionerror\n"); } printk("alloc_chrdev_regionok\n"); major_num = MAJOR(dev_num); minor_num= MINOR(dev_num); printk("major_num= %d\n",major_num); printk("minor_num= %d\n",minor_num); } cdev.owner = THIS_MODULE; cdev_init(&cdev,&chrdev_ops); cdev_add(&cdev,dev_num,DEVICE_NUMBER); return 0; } static void misc_exit(void) { unregister_chrdev_region(MKDEV(major_num,minor_num),DEVICE_NUMBER); cdev_del(&cdev); printk("misc goodbye"); } MODULE_LICENSE("GPL");
- 字符设备注册完以后并不会自动生成设备节点,杂项设备可以,我们需要用mknod命令创建一个设备节点,自动生成下一章讲
- mknod 想要新建设备节点的名称 类型(字符类型是c) 主设备号 次设备号
- mknod /dev/test c 247 0
- 然后新建一个测试.c,里面只需要打开/dev/test就可以看到成不成功了