Linux字符設備-內核態數據與用戶態數據互傳
_IO,_IOR,_IOW和_IORW的含義
對於系統支持設備的ioctl號,你可以在/usr/include下面的頭文件中找到,對於你自己的設備,如果需要使用ioctl接口,則需要定義自己 的ioctl號。以前的2.4中有個問題是,大家都隨便定義自己的ioctl號,造成很大可能性的重復性。一個壞處是難以管理,另外一個是容易造成錯誤, 例如如果用戶本來希望打開一個串口設備,結果通過open打開了網口,如果串口的某個ioctl號正好是網口的關閉操作,這樣就會造成錯誤。在2.6裡 面,你定義自己的ioctl號最好使用_IO, _IOR, _IOW和_IORW來定義,這些宏考慮了第三個參數的長度,設備的magic number,以及操作的方向等,避免了2.4中的問題
: _IO(type,nr)(給沒有參數的命令),
_IOR(type, nre, datatype)(給從驅動中讀數據的),
_IOW(type,nr,datatype)(給寫數據),
_IOWR(type,nr,datatype)(給雙向傳送).
type 和 number 成員作為參數被傳遞,
並且 size 成員通過應用 sizeof 到 datatype 參數而得到
int ioctl( int fd, int request, .../* void *arg */ ) 詳解
第三個參數總是一個指針,但指針的類型依賴於request 參數。我們可以把和網絡相關的請求劃分為6 類:
套接口操作
文件操作
接口操作
ARP 高速緩存操作
路由表操作
流系統
先寫一個內核態數據與用戶態數據互傳的例子及APP
手動安裝步驟:
Insmod my_char_dev.ko

不需要再安裝設備節點
然後是測試app
./my_char_dev_app 1

1 #include <linux/module.h>
2 #include <linux/init.h>
3 #include <linux/io.h>
4 #include <linux/fs.h>
5 #include <asm/device.h> //下面這三個頭文件是由於動態創建需要加的
6 #include <linux/device.h>
7 #include <linux/cdev.h>
8 #include "my_cdev.h"
9 #include <asm/uaccess.h>
10
11
12 struct cdev cdev;
13 dev_t devno;//這裡是動態分配設備號和動態創建設備結點需要用到的
14 struct class *cdev_class;
15 int param;
16 int my_cdev_open(struct inode *node,struct file *filp)
17 {
18 printk("my_cdev_open sucess!\n");
19 return 0;
20 }
21
22 long my_cdev_ioctl(struct file *filp ,unsigned int cmd ,unsigned long arg)
23 {
24 int rc = -1;
25
26 switch(cmd)
27 {
28 case LED_ON:
29 rc = copy_from_user(¶m, (int __user*)arg, 4);
30 if (0 != rc)
31 {
32 printk("copy_from_user failed.\n");
33 break;
34 }
35 printk("Param is %d.\n",param);
36 printk("CMD test: LED_ON is set!\n");
37 return 0;
38 case LED_OFF:
39 printk("CMD test: LED_OFF is set!\n");
40 param = 1000;
41 rc = copy_to_user((int __user*)arg,¶m,4);
42 if (0 != rc)
43 {
44 printk("copy_to_user failed.\n");
45 }
46 param = 0;
47 return 0;
48 default :
49 return -EINVAL;
50 }
51 }
52
53 struct file_operations my_cdev_fops=
54 {
55 .open = my_cdev_open,
56 .unlocked_ioctl = my_cdev_ioctl,
57
58 };
59
60 static int my_cdev_init(void)
61 {
62 int ret;
63 /**動態分配設備號*/
64 ret = alloc_chrdev_region(&devno,0,1,"my_chardev");
65 if(ret)
66 {
67 printk("alloc_chrdev_region fail!\n");
68 unregister_chrdev_region(devno,1);
69 return ret;
70 }
71 else
72 {
73 printk("alloc_chrdev_region sucess!\n");
74 }
75 /**描述結構初始化*/
76 cdev_init(&cdev,&my_cdev_fops);
77 /**描述結構注冊*/
78 ret = cdev_add(&cdev,devno,1);
79 if(ret)
80 {
81 printk("cdev add fail.\n");
82 unregister_chrdev_region(devno,1);
83 return ret;
84 }
85 else
86 {
87 printk("cdev add sucess!\n");
88 }
89
90 cdev_class = class_create(THIS_MODULE,"my_chardev");
91 if(IS_ERR(cdev_class))
92 {
93 printk("Create class fail!\n");
94 unregister_chrdev_region(devno,1);
95 return -1;
96 }
97 else
98 {
99 printk("Create class sucess!\n");
100 }
101
102 device_create(cdev_class,NULL,devno,0,"my_chardev");
103
104 return 0;
105 }
106 static void my_cdev_exit(void)
107 {
108 device_destroy(cdev_class,devno);
109 class_destroy(cdev_class);
110 cdev_del(&cdev);
111 unregister_chrdev_region(devno,1);
112 printk("my_cdev_exit sucess!\n");
113 }
114 module_init(my_cdev_init);
115 module_exit(my_cdev_exit);
116 MODULE_LICENSE("GPL");
117 MODULE_AUTHOR("YEFEI");
118 MODULE_DESCRIPTION("YEFEI Driver");
1 #ifndef __MY_CDEV_H__ 2 #define __MY_CDEV_H__ 3 4 #define LED_MAGIC 'L' 5 #define LED_ON _IOW(LED_MAGIC,0,int) 6 #define LED_OFF _IOR(LED_MAGIC,1,int *) 7 8 #endif
1 #include <sys/stat.h>
2 #include <sys/types.h>
3 #include <sys/ioctl.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include "my_cdev.h"
7
8 int main(int argc,char *argv[])
9 {
10 int fd;
11 int cmd;
12 long ret = 0;
13 unsigned long param = 0;
14 if(argc < 2)
15 {
16 printf("Please enter secend param!\n");
17 return 0;
18 }
19 cmd = atoi(argv[1]);
20 fd = open("/dev/my_chardev",O_RDWR);
21 if(fd < 0)
22 {
23 printf("Open dev/my_chardev fail!\n");
24 close(fd);
25 return 0;
26 }
27 switch(cmd)
28 {
29 case 1:
30 param = 500;
31 ret = ioctl(fd,LED_ON,¶m);
32 break;
33 case 2:
34 ret = ioctl(fd,LED_OFF,¶m);
35 printf("ret is %d. read data is %d.\n",ret,param);
36 break;
37 default:
38 break;
39 }
40 close(fd);
41 return 0;
42 }
1 obj-m := my_char_dev.o 2 KDIR := /home/win/dn377org/trunk/bcm7252/linux/ 3 all: 4 make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm 5 clean: 6 rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order