1.6介绍一种内核与用户空间通信的方法-misc设备ioctl机制
块设备驱动开发中往往需要配合用户态的管理程序工具,管理我们的块设备,此时我们需要涉及用户空间程序与块设备通信的方法,ioctl机制就是接下来需要学习和实战的,通过ioctl机制,用户态负责发送各种命令给内核驱动;内核态接收用户态发送的命令,并根据命令执行相应的动作,如下图所示。
ioctl提供用户态程序使用内核态函数的通道,此时需要注册一个字符设备来实现,我们使用misc这个字符设备来实现。
Ioctl.h
1 #ifndef _IOCTL_H
2 #define _IOCTL_H
3
4 /* misc device name*/
5 #define MISC_NAME "ioctl_test"
6
7 /**
8 *define ioctl codes for interfacing between kernel_module and user program
9 */
10 #define IOCTL_CODE 0xcc /* major type code - adjusted for target system */
11
12 #define TEST_CMD _IOWR (IOCTL_CODE, 0x09, unsigned long)
13
14 #endif
user.c
1 #include <sys/ioctl.h>
2 #include <unistd.h>
3 #include <fcntl.h>
4 #include <stdio.h>
5 #include "ioctl.h"
6
7 int main(void)
8 {
9 unsigned long arg = 2013;
10 int fd;
11
12 fd = open("/dev/"MISC_NAME, O_RDWR, 0);
13 if (fd < 0) {
14 printf("Failed to open/dev/%s\n", MISC_NAME);
15 goto out;
16 }
17
18 if (ioctl(fd, TEST_CMD, &arg) < 0) {
19 printf("Failed to executeioctl!\n");
20 }
21
22 close(fd);
23 out:
24 return 0;
25 }
kernel.c
1 /*
2 * IOCTL
3 *Author: talk@studio
4 */
5
6 #include <linux/fs.h>
7 #include <linux/uaccess.h>
8 #include <linux/module.h>
9 #include <linux/miscdevice.h>
10
11 #include "ioctl.h"
12
13 static int ioctl(struct inode *inode,struct file *file,
14 unsigned int cmd,unsigned long user)
15 {
16 unsigned long arg;
17 int ret = 0;
18
19 if (_IOC_TYPE(cmd) != IOCTL_CODE) {
20 printk("Unknown ioctlcommand 0x%x\n", cmd);
21 ret = -ENOTTY;
22 goto out;
23 }
24
25 switch (cmd) {
26 case TEST_CMD:
27 ret =copy_from_user(&arg, (unsigned long *)user, sizeof(unsigned lon g));
28 if (ret) {
29 printk("copy from user failed!\n");
30 } else {
31 printk("received IOctl[arg=%lu] from user!\n", arg);
32 }
33 break;
34 default:
35 printk("Unknownioctl command[0x%x].\n", cmd);
36 ret = -ENOTTY;
37 break;
38 }
39 out:
40 return ret;
41 }
42
43 static struct file_operations_misc_ctl_fops = {
44 .ioctl = ioctl,
45 .owner = THIS_MODULE,
46 };
47
48 static struct miscdevice _misc_dev = {
49 .minor = MISC_DYNAMIC_MINOR,
50 .name = MISC_NAME,
51 .fops = &_misc_ctl_fops
52 };
53
54 static int __init ioctl_init(void)
55 {
56 int ret;
57
58 ret = misc_register(&_misc_dev);
59 if (ret) { <