一、CDEV结构
|
二、file_operation 结构
|
三、为cdev申请内存
接下来,我们就需要为cdev申请内存,然后再通过cdev_init 函数将cdev与file_operation结构体联系起来,
|
最后通过cdev_add函数,将cdev添加到内核中
|
四、实例解析
1.自定义一个cdev结构体
如图所示,上述代码中,先自定义一个简单的cdev结构体key_dev,然后再实例化key_device, 接下来就定义一个我们接下来要操作的数组key_buff[MEM_SIZE],MEM_SIZE为自定义的内存的大小。
2.在init函数中初始化cdev结构体
当我们的应用程序调用open函数打开设备时,
在init函数中初始化cdev结构体,为cdev结构体开辟内存,连接cdev与fops结构体,注册cdev进入内核
3.一旦注册入内核,我们就可以开始使用了
当我们的应用程序打开设备时,在open函数中将filp的private_data赋值为我们所分配的key_device的结构体
4.释放cdev内存
当我们不用驱动时自然就要释放我们刚刚开辟的内存。
如图所示,首先删除cdev结构体,然后再使用kfree来释放cdev释放申请的内存
5.编译与测试
如图所示,我们在应用程序中先使用write函数往数组中写入'hello,Lover雪儿'的字符串,然后再使用read函数读取内容,但是,必须注意一点,在每次read后者write前,必须先使用lseek函数中重定位指针。
附上驱动程序源代码:
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13
14 #define DEVICE_NAME 'cdev'
15 #define Driver_NAME 'key_cdev'
16
17 #define KEY_MAJOR 220
18 #define KEY_MINOR 0
19 #define COMMAND1 1
20 #define COMMAND2 2
21 #define MEM_SIZE 256
22
23 struct key_dev {
24 struct cdev cdev;
25 };
26 struct key_dev *key_device;
27 static unsigned char key_buff[MEM_SIZE];
28
29 //auto to create device node
30 static struct class *drv_class = NULL;
31 static struct class_device *drv_class_dev = NULL;
32
33 static int key_open(struct inode *inode,struct file *filp){
34 filp->private_data = key_device;
35 return 0;
36 }
37
38 static int key_release(struct inode* inode,struct file *filp){
39 return 0;
40 }
41
42 static ssize_t key_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos){
43 ssize_t ret = 0;
44 loff_t pos = *f_pos;
45 if(pos > MEM_SIZE) //如果文件指针偏移超出文件大小
46 return ret = 0;
47 if(count > (MEM_SIZE - pos))
48 count = 256 - pos; //若内存不足,则写到内存满的位置
49 pos += count;
50 //读出数据
51 if(copy_to_user(buf,key_buff + *f_pos,count)){
52 return ret = -EFAULT;
53 }
54 *f_pos = pos;
55 return count;
56 }
57
58 static ssize_t key_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos){
59 ssize_t ret = -ENOMEM;
60 loff_t pos = *f_pos; //获取当前文件指针偏移
61 if(pos > MEM_SIZE) //如果文件指针偏移超出文件大小
62 return ret;
63 if(count > (MEM_SIZE - pos))
64 count = 256 - pos; //若内存不足,则写到内存满的位置
65 pos += count;
66 //从fops处开始写入数据
67 if(copy_from_user(key_buff + *f_pos,buf,count)){
68 ret = -EFAULT;
69 return ret;
70 }
71 *f_pos = pos;
72 return count;
73 }
74
75 static int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg){
76 switch(cmd){
77 case COMMAND1: printk('<0>ncommand 1 n'); break;
78 case COMMAND2: printk('<0>ncommand 2 n'); break;
79 default: printk('<0>command default n'); break;
80 }
81 return 0;
82 }
83
84 static loff_t key_llseek(struct file *filp, loff_t off, int whence){
85 loff_t pos;
86 pos = filp->f_pos; //获取文件指针当前位置
87 switch(whence){
88 case 0: pos = off; break; //重定位到文件开头