以前一直没有注意ioctl的实现的步骤,最近在做项目的时候,遇到了用户态和内核态的模块之间数据的通信,所以整理了一下ioctl的主要的实现过程。
1)首先先整体整理一下总的步骤
现在有以下文件:
1、内核态:内核态有文件busapi.c,这两个文件编译成内核模块——drvmain.ko。并且在文件busapi.h文件中,提供了很多供调用的函数接口。
2、用户态:用户态有文件tool.c,在tool.c文件中,主要是获取用户的输入,并且将用户的输入数据传递给busapi.h的函数接口,同时获取busapi.h函数接口返回的数据。
为了实现以上的数据之间的传递,我们创建文件ioctl.c和ioctl.h。并将这两个文件编译成内核模块ioctl.ko。
到目前为止,我们整个项目编译之后,会产生三个可执行程序:
1、drvmain.ko(由busapi.c编译生成)
2、tool(由tool.c编译生成)
3、ioctl.ko(由ioctl.c编译生成)
生成这三个文件后,我们加载的顺序是:
1、加载drvmain.ko
linux下的命令是:insmod drvmain.ko
2、加载ioctl.ko
linux下的命令是:insmod ioctl.ko
3、运行可执行程序tool
linux下的命令时:./tool
2)下面将介绍每一个文件的实现
1、busapi.c、busapi.h文件就不介绍它们的实现了,一般是在busapi.c中实现函数,在busapi.h中声明函数,提供接口给其他模块调用。
2、ioctl.h文件
在ioctl.h文件中主要是定义一下内容:
第一部分内容是:
#define IOCTO_TYPE 0xa4
#define IOCTO_CMD_READ _IOR(IOCTO_TYPE,0x01,int)
#define IOCTO_CMD_WRITE _IOW(IOCTO_TYPE,0x02,int)
#define IOCTO_CMD_DISPLAY _IOWR(IOCTO_TYPE,0x03,slaveInfo)
第二部分内容是:
typedef struct _SLAVE_INFO
{
int a;
int b;
} slaveInfo;
3、ioctl.c文件
第一部分:
#include "ioctl.h"
#include "busapi.h"
第二部分:
static struct file_operations fop =
{
.owner = THIS_MODULE,
.open = FileOpen,
.ioctl = FileIoctl,
.release = FileRlease,
};
第三部分:
实现第二部分定义的函数
int FileOpen(struct inode *inode, struct file *filp)
{
主要放你想要在调用open()函数是需要实现的代码;
}
int FileIoctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
switch (cmd)
{
case IOCTL_CMD_READ:
break;
case IOCTL_CMD_WRITE:
break;
case IOCTL_CMD_DISPLAY:
SlaveInfo data;
int input;
int output=100;
copy_from_user(&data,(void __user *)arg, sizeof(data);
input = data.b;
output = (busapi.h文件中的函数接口)(input);
data.a = ouput;
copy_to_user((void __user *) arg, &data, sizeof(data));
break;
default:
break;
}
}
int FileRelease(struct inode *inode, struct file *filp)
{
主要放你想要在调用close()函数是需要实现的代码;
}
第四部分:
int major = 0;// 表示自动分配设备号
void __init InitModule(void)
{
major = register_chrdev(major,"filedev",&fop);
}
void __exit ExitModule(void)
{
unregister_chrdev(major,&fop);
}
module_init(InitModule);
module_exit(ExitModule);
4、tool.c文件
第一部分:
#include "ioctl.h"
void main (void)
{
SlaveInfo dev;
int fd =0;
fd = open("/dev/filedev",O_RDWR);
dev.b = 10;
ioctl(fd,IOCTO_CMD_DISPLAY,&dev);
printf( "%d",dev.a);
close(fd);
}