驱动开发之read/write:
系统中一切的读写都是站在用户空间的角度来考虑(把你自己当做用户空间)
什么是输入/读?数据从内核空间流向用户空间
什么是输出/写?数据从用户空间流向内核空间
read:
应用层:
1ssize_t read(int fd, void *buf, size_t count);
参数1:文件描述符
参数2:存放读取到的数据的空间首地址
参数3:空间大小(不是读到的数据大小)
返回值:成功读取到的字节数
驱动层:
1ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
参数1:
参数2:应用层read函数的参数2
参数3:应用层read函数的参数3
参数4:文件指针偏移量
返回值:正确读取的字节数
驱动层中实现读功能:
1
2static inline long copy_to_user(void __user *to,const void *from, unsigned long n);
参数1:用户空间缓存区首地址
参数2:内核空间的缓存区首地址
参数3:实际拷贝的字节数
返回值:0成功,非0出错
write:
应用层:
1ssize_t write(int fd, const void *buf, size_t count);
参数1:
参数2:存放数据的空间首地址
参数3:实际写的字节数
驱动层:
1ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
参数1:
参数2:应用层write函数的参数2
参数3:应用层write函数的参数3
参数4:文件指针偏移量
返回值:正确写入的字节数
驱动层中实现写功能:
1static inline long copy_from_user(void *to,const void __user * from, unsigned long n)
参数1:内核空间的缓存区首地址
参数2:用户空间缓存区首地址
参数3:实际拷贝的字节数
返回值:0成功,非0出错


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
371 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 6 int main(int argc, const char *argv[]) 7 { 8 int fd; 9 10 fd = open("/dev/demo",O_RDWR); 11 if(fd == -1) 12 { 13 perror("open"); 14 return -1; 15 } 16 17 char buf[64]; 18 read(fd,buf,sizeof(buf)); 19 printf("%sn",buf); 20 21 write(fd,"I am from user",15); 22 close(fd); 23 return 0; 24 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77#include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> #include <asm/uaccess.h> MODULE_LICENSE("GPL"); int major; struct class *cls; struct device *devs; char krbuf[1024] = "I am from kernel"; char kwbuf[1024]; int demo_open(struct inode *inode,struct file *filp) { return 0; } int demo_close(struct inode *inode,struct file *filp) { return 0; } ssize_t demo_read(struct file *filp,char __user *ubuf,size_t size,loff_t *off) { // printk("demo_readn"); // strncpy(ubuf,krbuf,strlen(krbuf) + 1); // return strlen(krbuf) + 1; int ret; ssize_t n; if(strlen(krbuf) + 1 > size) n = size; else n = strlen(krbuf) + 1; ret = copy_to_user(ubuf,krbuf,n); if(ret != 0) { return -EFAULT; } return n; } ssize_t demo_write(struct file *filp,const char __user *ubuf,size_t size,loff_t *off) { ssize_t n; int ret; if(size > sizeof(kwbuf)) n = sizeof(kwbuf); else n = size; ret = copy_from_user(kwbuf,ubuf,n); if(ret != 0) return -EFAULT; printk("%sn",kwbuf); return n; } struct file_operations fops = { .owner = THIS_MODULE, .open = demo_open, .read = demo_read, .write = demo_write, .release = demo_close, }; int demo_init(void) { major = register_chrdev(0,"demo",&fops); cls = class_create(THIS_MODULE,"demo"); devs = device_create(cls,NULL,MKDEV(major,0),NULL,"demo"); return 0; } module_init(demo_init); void demo_exit(void) { device_destroy(cls,MKDEV(major,0)); class_destroy(cls); unregister_chrdev(major,"demo"); return; } module_exit(demo_exit);
分支匹配函数:
应用层:
1int ioctl(int fd, int request, ...);
参数1:文件描述符
参数2:命令——用来和驱动中的某个分支匹配
参数3:可以没有参数
可以有参数(只能有一个),有参数时可以传递变量名或者变量地址,不能是常量。
1long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
参数1:
参数2:接收应用层ioctl的参数2
参数3:如果应用层参数3没有传参,此参数没有值
如果应用层参数3传递的是变量名,此参数接收了变量的内容
如果应用层参数3传递的是变量的地址,此参数接收的就是变量地址
命令的封装方法:
命令本身是一个32位无符号整数,这32位被分成了4个部分(方向,数据类型大小,幻数,序号)
1
2
3
4
5
6#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) #define _IOC(dir,type,nr,size) (((dir) << _IOC_DIRSHIFT) ((type) << _IOC_TYPESHIFT) ((nr) << _IOC_NRSHIFT) ((size) << _IOC_SIZESHIFT))
dir代表方向
type代表幻数
nr代表序号
size代表数据类型大小
1
2
3#define _IOC_TYPESHIFT 8 #define _IOC_SIZESHIFT 16 #define _IOC_DIRSHIFT 30
命令 = 方向 << 30 | 数据类型大小 << 16 | 幻数 << 8 | 序号 << 0
方向占2位:无读写数据、只读数据、只写数据、读写数据
数据类型大小占14位:
幻数占8位:如何选择幻数必须查看Documetation/ioctl/ioctl-number.txt
序号占8位:
命令的封装需要调用:
1
2
3
4_IO(幻数,序号) _IOR(幻数,序号,数据类型) _IOW(幻数,序号,数据类型) _IOWR(幻数,序号,数据类型)
ioctl代码:
1:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
181 struct test 2 { 3 int a; 4 char b; 5 }; 6 7 #define DEMO_CMD1 _IO('x',0) 8 #define DEMO_CMD2 _IO('x',1) 9 #define DEMO_CMD3 _IOW('x',2,int) 10 #define DEMO_CMD4 _IOW('x',3,int) 11 #define DEMO_CMD5 _IOW('x',4,struct test)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
551 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 struct test t = { 9 .a = 100, 10 .b = 'w', 11 }; 12 13 int main(int argc, const char *argv[]) 14 { 15 int fd; 16 17 fd = open("/dev/demo",O_RDWR); 18 if(fd == -1) 19 { 20 perror("open"); 21 return -1; 22 } 23 24 // ioctl(fd,1); 25 // ioctl(fd,2); 26 27 ioctl(fd,DEMO_CMD1); 28 ioctl(fd,DEMO_CMD2); 29 30 int a = 10; 31 ioctl(fd,DEMO_CMD3,a); 32 ioctl(fd,DEMO_CMD4,&a); 33 ioctl(fd,DEMO_CMD5,&t); 34 close(fd); 35 return 0; 36 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
1311 #include <linux/init.h> 2 #include <linux/module.h> 3 #include <linux/fs.h> 4 #include <linux/device.h> 5 #include <asm/uaccess.h> 6 #include "head.h" 7 8 MODULE_LICENSE("GPL"); 9 10 int major; 11 struct class *cls; 12 struct device *devs; 13 14 int demo_open(struct inode *inode,struct file *filp) 15 { 16 return 0; 17 } 18 19 long demo_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) 20 { 21 int ret; 22 int a; 23 struct test t; 24 switch(cmd) 25 { 26 #if 0 27 case 1: 28 printk("first cmdn"); 29 break; 30 case 2: 31 printk("second cmdn"); 32 break; 33 #endif 34 case DEMO_CMD1: 35 printk("first cmdn"); 36 break; 37 case DEMO_CMD2: 38 printk("second cmdn"); 39 break; 40 case DEMO_CMD3: 41 printk("%ldn",arg); 42 break; 43 case DEMO_CMD4: 44 a = *((int *)arg); 45 printk("%dn",a); 46 break; 47 case DEMO_CMD5: 48 ret = copy_from_user(&t,(struct test *)arg,sizeof(struct test)); 49 printk("%d,%cn",t.a,t.b); 50 break; 51 52 } 53 return 0; 54 } 55 56 int demo_close(struct inode *inode,struct file *filp) 57 { 58 return 0; 59 } 60 61 struct file_operations fops = { 62 .owner = THIS_MODULE, 63 .open = demo_open, 64 .unlocked_ioctl = demo_ioctl, 65 .release = demo_close, 66 }; 67 68 int demo_init(void) 69 { 70 major = register_chrdev(0,"demo",&fops); 71 72 cls = class_create(THIS_MODULE,"demo"); 73 74 devs = device_create(cls,NULL,MKDEV(major,0),NULL,"demo"); 75 76 return 0; 77 } 78 module_init(demo_init); 79 80 void demo_exit(void) 81 { 82 device_destroy(cls,MKDEV(major,0)); 83 class_destroy(cls); 84 unregister_chrdev(major,"demo"); 85 return; 86 } 87 module_exit(demo_exit);
2.led:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
571 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 int main(int argc, const char *argv[]) 9 { 10 int fd; 11 12 fd = open("/dev/led",O_RDWR); 13 14 while(1) 15 { 16 ioctl(fd,LED2_ON); 17 sleep(1); 18 ioctl(fd,LED3_ON); 19 sleep(1); 20 ioctl(fd,LED1_ON); 21 sleep(1); 22 ioctl(fd,LED4_ON); 23 sleep(1); 24 25 ioctl(fd,LED4_OFF); 26 sleep(1); 27 ioctl(fd,LED3_OFF); 28 sleep(1); 29 ioctl(fd,LED1_OFF); 30 sleep(1); 31 ioctl(fd,LED2_OFF); 32 sleep(1); 33 } 34 return 0; 35 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
1461 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/fs.h> 4 #include <linux/device.h> 5 #include <asm/io.h> 6 #include "head.h" 7 8 #define GPX2CON 0x11000c40 9 #define GPX1CON 0x11000c20 10 #define GPF3CON 0x114001e0 11 12 unsigned int *gpx2con; 13 unsigned int *gpx2dat; 14 unsigned int *gpx1con; 15 unsigned int *gpx1dat; 16 unsigned int *gpf3con; 17 unsigned int *gpf3dat; 18 19 int fs4412_led_major; 20 struct class *cls; 21 struct device *devs; 22 23 int fs4412_led_open(struct inode *inode,struct file *filp) 24 { 25 return 0; 26 } 27 28 long fs4412_led_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) 29 { 30 switch(cmd) 31 { 32 case LED2_ON: 33 writel((readl(gpx2dat) & ~(1 << 7)) | 1 << 7,gpx2dat); 34 break; 35 case LED2_OFF: 36 writel((readl(gpx2dat) & ~(1 << 7)),gpx2dat); 37 break; 38 case LED1_ON: 39 writel((readl(gpx1dat) & ~(1 << 0)) | 1 << 0,gpx1dat); 40 break; 41 case LED1_OFF: 42 writel((readl(gpx1dat) & ~(1 << 0)),gpx1dat); 43 break; 44 case LED3_ON: 45 writel((readl(gpf3dat) & ~(1 << 4)) | 1 << 4,gpf3dat); 46 break; 47 case LED3_OFF: 48 writel((readl(gpf3dat) & ~(1 << 4)),gpf3dat); 49 break; 50 case LED4_ON: 51 writel((readl(gpf3dat) & ~(1 << 5)) | 1 << 5,gpf3dat); 52 break; 53 case LED4_OFF: 54 writel((readl(gpf3dat) & ~(1 << 5)),gpf3dat); 55 break; 56 } 57 return 0; 58 } 59 60 struct file_operations fs4412_led_ops = { 61 .owner = THIS_MODULE, 62 .open = fs4412_led_open, 63 .unlocked_ioctl = fs4412_led_ioctl, 64 }; 65 66 int __init fs4412_led_init(void) 67 { 68 fs4412_led_major = register_chrdev(0,"led",&fs4412_led_ops); 69 cls = class_create(THIS_MODULE,"led"); 70 devs = device_create(cls,NULL,MKDEV(fs4412_led_major,0),NULL,"led"); 71 72 gpx2con = ioremap(GPX2CON,4); 73 gpx2dat = gpx2con + 1; 74 75 gpx1con = ioremap(GPX1CON,4); 76 gpx1dat = gpx1con + 1; 77 78 gpf3con = ioremap(GPF3CON,4); 79 gpf3dat = gpf3con + 1; 80 81 writel((readl(gpx2con) & ~(0xf << 28)) | 1 << 28,gpx2con); 82 writel((readl(gpx1con) & ~(0xf << 0)) | 1 << 0,gpx1con); 83 writel((readl(gpf3con) & ~(0xff << 16)) | 0x11 << 16,gpf3con); 84 85 return 0; 86 } 87 module_init(fs4412_led_init); 88 89 void __exit fs4412_led_exit(void) 90 { 91 device_destroy(cls,MKDEV(fs4412_led_major,0)); 92 class_destroy(cls); 93 unregister_chrdev(fs4412_led_major,"led"); 94 return; 95 } 96 module_exit(fs4412_led_exit); 97 MODULE_LICENSE("GPL");
3.资源的竞争


1
2
3
41 #define LED_ON _IO('x',0) 2 #define LED_OFF _IO('x',1)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
331 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 int main(int argc, const char *argv[]) 9 { 10 int fd; 11 12 fd = open("/dev/led0",O_RDWR); 13 14 while(1) 15 { 16 ioctl(fd,LED_ON); 17 sleep(1); 18 19 ioctl(fd,LED_OFF); 20 sleep(1); 21 } 22 return 0; 23 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
331 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 int main(int argc, const char *argv[]) 9 { 10 int fd; 11 12 fd = open("/dev/led1",O_RDWR); 13 14 while(1) 15 { 16 ioctl(fd,LED_ON); 17 sleep(1); 18 19 ioctl(fd,LED_OFF); 20 sleep(1); 21 } 22 return 0; 23 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
331 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 int main(int argc, const char *argv[]) 9 { 10 int fd; 11 12 fd = open("/dev/led2",O_RDWR); 13 14 while(1) 15 { 16 ioctl(fd,LED_ON); 17 sleep(1); 18 19 ioctl(fd,LED_OFF); 20 sleep(1); 21 } 22 return 0; 23 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
331 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 #include <sys/ioctl.h> 6 #include "head.h" 7 8 int main(int argc, const char *argv[]) 9 { 10 int fd; 11 12 fd = open("/dev/led3",O_RDWR); 13 14 while(1) 15 { 16 ioctl(fd,LED_ON); 17 sleep(1); 18 19 ioctl(fd,LED_OFF); 20 sleep(1); 21 } 22 return 0; 23 }


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
2451 #include <linux/module.h> 2 #include <linux/init.h> 3 #include <linux/fs.h> 4 #include <linux/device.h> 5 #include <asm/io.h> 6 #include "head.h" 7 8 #define GPX2CON 0x11000c40 9 #define GPX1CON 0x11000c20 10 #define GPF3CON 0x114001e0 11 12 unsigned int *gpx2con; 13 unsigned int *gpx2dat; 14 unsigned int *gpx1con; 15 unsigned int *gpx1dat; 16 unsigned int *gpf3con; 17 unsigned int *gpf3dat; 18 19 int fs4412_led_major; 20 struct class *cls; 21 struct device *devs; 22 23 int fs4412_led_open(struct inode *inode,struct file *filp) 24 { 25 int num; 26 num = iminor(inode);//获取次设备号 27 filp->private_data = (void *)num; 28 return 0; 29 } 30 31 void fs4412_led_on(int num) 32 { 33 switch(num) 34 { 35 case 0: 36 //点亮地一个灯 37 break; 38 case 1: 39 break; 40 case 2: 41 break; 42 case 3: 43 break; 44 } 45 } 46 47 void fs4412_led_off(int num) 48 { 49 switch(num) 50 { 51 case 0: 52 //关闭地一个灯 53 break; 54 case 1: 55 break; 56 case 2: 57 break; 58 case 3: 59 break; 60 } 61 } 62 63 64 long fs4412_led_ioctl(struct file *filp,unsigned int cmd,unsigned long arg) 65 { 66 int num; 67 num = (int)filp->private_data; 68 switch(cmd) 69 { 70 case LED_ON: 71 fs4412_led_on(num); 72 break; 73 case LED_OFF: 74 fs4412_led_off(num); 75 break; 76 #if 0 77 case LED2_ON: 78 writel((readl(gpx2dat) & ~(1 << 7)) | 1 << 7,gpx2dat); 79 break; 80 case LED2_OFF: 81 writel((readl(gpx2dat) & ~(1 << 7)),gpx2dat); 82 break; 83 case LED1_ON: 84 writel((readl(gpx1dat) & ~(1 << 0)) | 1 << 0,gpx1dat); 85 break; 86 case LED1_OFF: 87 writel((readl(gpx1dat) & ~(1 << 0)),gpx1dat); 88 break; 89 case LED3_ON: 90 writel((readl(gpf3dat) & ~(1 << 4)) | 1 << 4,gpf3dat); 91 break; 92 case LED3_OFF: 93 writel((readl(gpf3dat) & ~(1 << 4)),gpf3dat); 94 break; 95 case LED4_ON: 96 writel((readl(gpf3dat) & ~(1 << 5)) | 1 << 5,gpf3dat); 97 break; 98 case LED4_OFF: 99 writel((readl(gpf3dat) & ~(1 << 5)),gpf3dat); 100 break; 101 #endif 102 } 103 return 0; 104 } 105 106 struct file_operations fs4412_led_ops = { 107 .owner = THIS_MODULE, 108 .open = fs4412_led_open, 109 .unlocked_ioctl = fs4412_led_ioctl, 110 }; 111 112 int __init fs4412_led_init(void) 113 { 114 int i; 115 fs4412_led_major = register_chrdev(0,"led",&fs4412_led_ops); 116 cls = class_create(THIS_MODULE,"led"); 117 118 for(i = 0;i < 4;i ++) 119 devs = device_create(cls,NULL,MKDEV(fs4412_led_major,i),NULL,"led%d",i); 120 121 gpx2con = ioremap(GPX2CON,4); 122 gpx2dat = gpx2con + 1; 123 124 gpx1con = ioremap(GPX1CON,4); 125 gpx1dat = gpx1con + 1; 126 127 gpf3con = ioremap(GPF3CON,4); 128 gpf3dat = gpf3con + 1; 129 130 writel((readl(gpx2con) & ~(0xf << 28)) | 1 << 28,gpx2con); 131 writel((readl(gpx1con) & ~(0xf << 0)) | 1 << 0,gpx1con); 132 writel((readl(gpf3con) & ~(0xff << 16)) | 0x11 << 16,gpf3con); 133 134 return 0; 135 } 136 module_init(fs4412_led_init); 137 138 void __exit fs4412_led_exit(void) 139 { 140 int i; 141 for(i = 3;i >= 0;i --) 142 device_destroy(cls,MKDEV(fs4412_led_major,i)); 143 class_destroy(cls); 144 unregister_chrdev(fs4412_led_major,"led"); 145 return; 146 } 147 module_exit(fs4412_led_exit); 148 MODULE_LICENSE("GPL");
总结:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39struct file_operations { ssize_t (*read)(struct file *filp,char __user *ubuf,size_t size,loff_t *off); ssize_t (*write)(struct file *filp,const char __user *ubuf,size_t size,loff_t *off); long (*unlock_ioctl)(struct file *filp,unsigned int cmd,unsigned long arg); }; 读写都是站在用户空间的角度来考虑 输入:数据从内核空间流向用户空间 输出:数据从用户空间流向内核空间 应用层:ssize_t read(int fd,void *buf,size_t size); 驱动层:ssize_t (*read)(struct file *filp,char __user *ubuf,size_t size,loff_t *off); int copy_to_user(void *to,void *from,size_t size); 应用层:ssize_t write(int fd,const void *buf,size_t size); 驱动层:ssize_t (*write)(struct file *filp,const char __user *ubuf,size_t size,loff_t *off); int copy_from_user(void *to,void *from,size_t size); 应用层:int ioctl(int fd,int cmd,...) 驱动层:long (*unlock_ioctl)(struct file *filp,unsigned int cmd,unsigned long arg); 命令分成了4个部分: 2位方向、14位数据类型大小、8位幻数、8位序号 设置命令需要调用一些宏函数: _IO(幻数,序号); _IOR(幻数,序号,数据类型); _IOW(幻数,序号,数据类型); _IOWR(幻数,序号,数据类型); 避免冲突需要查看Documetation/ioctl/ioctl-number.txt: 查看幻数和序号配合使用时哪些值会有冲突。 假设:4个灯,使不同的设备文件(led0 led1 led2 led3)操作不同的led灯。 相应的可以有4个进程,每个进程打开一个设备文件。这四个进程访问的是同一个驱动。 在操作驱动接口时调用的也是相同的接口,这种情况下会造成资源的竞争。 int led_open(struct inode *,struct file *) { num = iminor(inode); filp->private_data = (void *)num; } long led_ioctl() { int num; num = (int)filp->private_data; }
转载于:https://www.cnblogs.com/hslixiqian/p/9655949.html
最后
以上就是紧张乌龟最近收集整理的关于驱动开发之read/write驱动开发之read/write:的全部内容,更多相关驱动开发之read/write驱动开发之read/write内容请搜索靠谱客的其他文章。
发表评论 取消回复