_ioctl传递数组结构体
demo.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "demo.h"
#define CNAME "myled"
unsigned int major;
int myled_open(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
long myled_ioctl(struct file *file, unsigned int cmd, unsigned long args)
{
char kbuf[128] = {};
image_t kimage;
int ret;
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
//判断命令码
switch(cmd)
{
case UACCESS_BUF:
ret = copy_from_user(kbuf,(void*)args,GET_CMD_SIZE(UACCESS_BUF)); //用户空间数据拷贝到内核空间
if(ret){
printk("copy from user is buf error\n");
return -EIO;
}
printk("kbuf = %s\n",kbuf); //打印内核空间中的kbuf内容
break;
case UACCESS_STRUCT:
ret = copy_from_user(&kimage,(void*)args,GET_CMD_SIZE(UACCESS_STRUCT)); //用户空间数据拷贝到内核空间
if(ret){
printk("copy from user is struct error\n");
return -EIO;
}
printk("kernel height = %d width = %d\n",kimage.height,kimage.width); //打印内核空间结构体的值
kimage.height += 10;
kimage.width += 10;
ret = copy_to_user((void*)args,&kimage,GET_CMD_SIZE(UACCESS_STRUCT));//内核空间数据,传递到用户空间
if(ret){
printk("copy to user is struct error\n");
return -EIO;
}
break;
}
return 0;
}
int myled_close(struct inode *inode, struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
//操作方法结构体
const struct file_operations fop = {
.open = myled_open,
.unlocked_ioctl = myled_ioctl,
.release = myled_close,
};
//入口 insmod
static int __init demo_init(void)
{
//注册字符设备驱动
major = register_chrdev(0,CNAME,&fop);
if(major < 0){
printk("register chrdev is error\n");
return -EIO;
}
printk("major = %d\n",major); //打印主设备号的值
return 0;
}
//出口 rmmod
static void __exit demo_exit(void)
{
//注销字符设备驱动
unregister_chrdev(major,CNAME);
}
module_init(demo_init);//指定入口函数地址
module_exit(demo_exit);//指定出口函数地址
MODULE_LICENSE("GPL");//许可证
demo.h
#ifndef __DEMO_H__
#define __DEMO_H__
char buf[128] = "";
typedef struct{
int height;
int width;
}image_t;
#define UACCESS_BUF _IOW('A',1,char [128]) //传递字符数组命令码
#define UACCESS_STRUCT _IOWR('A',1,image_t) //传递结构体命令码
#define GET_CMD_SIZE(cmd) (cmd >> 16 & 0x3fff) //获取命令码大小
#endif
test.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include "demo.h"
int main(int argc,const char * argv[])
{
int fd = -1;
char buf[128] = "hello DC23121";
image_t uimage;
uimage.height = 100;
uimage.width= 20;
fd = open("/dev/myled",O_RDWR);//打开设备文件
if(fd == -1){
perror("open is error");
exit(1);
}
ioctl(fd,UACCESS_BUF,buf);//传递数组
ioctl(fd,UACCESS_STRUCT,&uimage);//传递结构体
printf("user height = %d width = %d\n",uimage.height,uimage.width);
close(fd);//关闭文件描述符
return 0;
}