什么叫异步io,阻塞io如果应用程序读取时时条件不满足,则会阻塞,进程随眠,效率低下,而异步io可以实现应该程序发送读请求的之后继续执行后面的代码,当条件满足的时候内核会发信号让应用程序可以处理,提高效率。函数说明:
应用层:
1. flag = fcntl(fd,F_GETFL,0);
功能描述:先获得文件描述符的属性
2. flag |= FASYNC ;
功能描述:修改文件描述符的属性(异步io)
3. fcntl(fd,F_SETFL,flag);
功能描述:设置属性成异步io,会调用内核的fasync函数
4. fcntl(fd,F_SETOWN,getpid());
功能描述:使内核收到数据后发送SIGIO(29号)信号给本进程
5. signal(29,myfun);
功能描述:应用程序收到信号后的处理函数
内核层:
6. fasync_helper(fd, pfile, mode, &pfasync);
功能描述:使文件具备异步通知功能
7. kill_fasync(&pfasync,29,POLL_IN);
功能描述:发送信号给用户程序
代码实现:
A.cpp在发送读请求后编进入死循环,当B.cpp执行以后内核会发信号给A.cpp处理
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include "linux/cdev.h"
#include "linux/kdev_t.h"
#include "linux/fs.h"
#include "asm/uaccess.h"
#include "linux/sched.h"
MODULE_LICENSE ("GPL");
struct cdev myuart;
int major = 200;
int minor = 2;
dev_t dev_id;
char kernel_buf[64] = {0};
struct fasync_struct *pfasync; 1.实例化结构体
struct file_operations var;
int myopen(struct inode *pinode, struct file *pfile)
{
printk(KERN_INFO "myopen run\n");
return 0;
}
int myclose(struct inode *pinode, struct file *pfile)
{
printk(KERN_INFO "myclose run\n");
return 0;
}
ssize_t myread(struct file *pfile, char __user *buf, size_t len, loff_t *off)
{
int ret = 0;
printk(KERN_INFO "myread run\n");
ret = copy_to_user(buf,kernel_buf,19);
return 19-ret;
}
ssize_t mywrite(struct file *pfile, const char __user *buf, size_t len, loff_t *off)
{
int ret;
ret = copy_from_user(kernel_buf,buf,len) ;
printk(KERN_INFO "mywrite fun run ret = %d\n",ret) ;
kill_fasync(&pfasync,29,POLL_IN); 2.发送信号给用户程序
return 30;
}
int myfasync(int fd, struct file *pfile, int mode)
{
printk(KERN_INFO "myfasync function run\n");
fasync_helper(fd, pfile, mode, &pfasync); 2.使文件具备异步通知机制
return 0;
}
static int __init hello_init (void)
{
int ret = 0;
int ret1;
dev_id = MKDEV(major,minor) ;
ret = register_chrdev_region(dev_id,1, "uart");
if(ret == -1)
{
printk(KERN_INFO "dev_id = %d can't use \n",major);
ret1 = alloc_chrdev_region(&dev_id,minor,1, "uart");
if(ret1 == -1)
{
printk(KERN_INFO "dev_id error \n");
return -1;
}
else
{
printk(KERN_INFO "major = %d \n", MAJOR(dev_id));
}
}
else
{
printk(KERN_INFO "major = %d can use \n",major);
}
var.open = myopen;
var.release = myclose;
var.write = mywrite;
var.read = myread;
var.fasync = myfasync; 2.要用到fasync函数使得设备具有异步通知功能
cdev_init(&myuart,&var);
cdev_add(&myuart,dev_id,1);
printk (KERN_INFO "driver init");
return 0;
}
static void __exit hello_exit (void)
{
unregister_chrdev_region(dev_id, 1);
cdev_del(&myuart);
printk (KERN_INFO "driver exit");
}
module_init (hello_init);
module_exit (hello_exit);
A.c代码,发送读取请求
#include "stdio.h"
#include "fcntl.h"
#include "stdlib.h"
#include "unistd.h"
int fd;
void myfun(int sig) 5.应用程序收到信号后的处理函数
{
char buf[64] = {0};
if(sig == 29)
{
read(fd,buf,64) ;
printf("buf = %s\n",buf) ;
}
return ;
}
int main()
{
int flag;
int len;
int i = 0;
fd = open("./kkk.c",O_RDWR,0777);
if(fd == -1)
{
printf("open error\n");
return -1;
}
flag = fcntl(fd,F_GETFL,0); 1.先获得文件描述符的属性
flag |= FASYNC ; 2.修改文件描述符的属性(异步io)
fcntl(fd,F_SETFL,flag); 3.设置属性成异步io,会调用内核的fasync函数
fcntl(fd,F_SETOWN,getpid()); 4.使内核收到数据后发送SIGIO(29号)信号给本进程
signal(29,myfun); 5.应用程序收到信号后的处理函数
while(1)
{
i ++;
printf("process some things i = %d\n",i);
sleep(1);
}
close(fd);
return 0;
}
B.c代码,向内核写入数据
#include "stdio.h"
#include "fcntl.h"
#include "stdlib.h"
#include "unistd.h"
#include "string.h"
int main()
{
int fd;
int len;
char buf[64] = {0};
fd = open("./kkk.c",O_RDWR,0777);
if(fd == -1)
{
printf("open error\n");
return -1;
}
while(1)
{
printf("please input send to kernel data\n");
scanf("%s",buf);
len = write(fd,buf,64);
memset(buf,0,64);
}
close(fd);
return 0;
}
转载请注明原文地址:https://ipadbbs.8miu.com/read-18507.html