Linux字符设备-内核态数据与用户态数据互传

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

#include <linux/module.h>#include <linux/init.h>#include <linux/io.h>#include <linux/fs.h>#include <asm/device.h> //下面这三个头文件是由于动态创建需要加的#include <linux/device.h>#include <linux/cdev.h>#include “my_cdev.h”#include <asm/uaccess.h>

struct cdev cdev;dev_t devno;//这里是动态分配设备号和动态创建设备结点需要用到的struct class *cdev_class;int param;int my_cdev_open(struct inode *node,struct file *filp){ printk(“my_cdev_open sucess!\n”); return 0;}

long my_cdev_ioctl(struct file *filp ,unsigned int cmd ,unsigned long arg){ int rc = -1;

switch(cmd) { case LED_ON: rc = copy_from_user(&param, (int __user*)arg, 4); if (0 != rc) { printk(“copy_from_user failed.\n”); break; } printk(“Param is %d.\n”,param); printk(“CMD test: LED_ON is set!\n”); return 0; case LED_OFF: printk(“CMD test: LED_OFF is set!\n”); param = 1000; rc = copy_to_user((int __user*)arg,&param,4); if (0 != rc) { printk(“copy_to_user failed.\n”); } param = 0; return 0; default : return -EINVAL; }}

struct file_operations my_cdev_fops={ .open = my_cdev_open, .unlocked_ioctl = my_cdev_ioctl,

};

static int my_cdev_init(void){ int ret; /**动态分配设备号*/ ret = alloc_chrdev_region(&devno,0,1,”my_chardev”); if(ret) { printk(“alloc_chrdev_region fail!\n”); unregister_chrdev_region(devno,1); return ret; } else { printk(“alloc_chrdev_region sucess!\n”); } /**描述结构初始化*/ cdev_init(&cdev,&my_cdev_fops); /**描述结构注册*/ ret = cdev_add(&cdev,devno,1); if(ret) { printk(“cdev add fail.\n”); unregister_chrdev_region(devno,1); return ret; } else { printk(“cdev add sucess!\n”); }

cdev_class = class_create(THIS_MODULE,”my_chardev”); if(IS_ERR(cdev_class)) { printk(“Create class fail!\n”); unregister_chrdev_region(devno,1); return -1; } else { printk(“Create class sucess!\n”); }

device_create(cdev_class,NULL,devno,0,”my_chardev”); return 0;}static void my_cdev_exit(void){ device_destroy(cdev_class,devno); class_destroy(cdev_class); cdev_del(&cdev); unregister_chrdev_region(devno,1); printk(“my_cdev_exit sucess!\n”);}module_init(my_cdev_init);module_exit(my_cdev_exit);MODULE_LICENSE(“GPL”);MODULE_AUTHOR(“YEFEI”);MODULE_DESCRIPTION(“YEFEI Driver”);

——————————————–

#ifndef __MY_CDEV_H__#define __MY_CDEV_H__

#define LED_MAGIC ‘L’#define LED_ON _IOW(LED_MAGIC,0,int)#define LED_OFF _IOR(LED_MAGIC,1,int *)

#endif

——————————————–

#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <fcntl.h>#include <stdio.h>#include “my_cdev.h”

int main(int argc,char *argv[]){ int fd; int cmd; long ret = 0; unsigned long param = 0; if(argc < 2) { printf(“Please enter secend param!\n”); return 0; } cmd = atoi(argv[1]); fd = open(“/dev/my_chardev”,O_RDWR); if(fd < 0) { printf(“Open dev/my_chardev fail!\n”); close(fd); return 0; } switch(cmd) { case 1: param = 500; ret = ioctl(fd,LED_ON,&param); break; case 2: ret = ioctl(fd,LED_OFF,&param); printf(“ret is %d. read data is %d.\n”,ret,param); break; default: break; } close(fd); return 0;}

——————————————–

1 obj-m := my_char_dev.o2 KDIR := /home/win/dn377org/trunk/bcm7252/linux/3 all:4 make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm5 clean:6 rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.bak *.order

想要成功,就一定要和成功的人在一起,不然反之

Linux字符设备-内核态数据与用户态数据互传

相关文章:

你感兴趣的文章:

标签云: