异步 IO

异步 IOIO分类阻塞IO非阻塞IOIO复用(select)异步IO(信号驱动的IO)IO类型1、异步通知:一旦设备就绪,则主动通知应用程序。异步通知意味则设备通知自身可访问,实现了异步I/O.由内核向应用程序发信号,类似中断。2、阻塞I/O意味着一直等待设备可访问后再访问。3、非阻塞IO,设备不可访问,则马上返回。4、轮询I/O,使用poll()查询设备是否可访问。Linux中最为常见信号的含义及其默认操作,详见Linux信号列表.pdf。重点关注的信号:SIGIO键盘输入或

IO分类

  1. 阻塞IO
  2. 非阻塞IO
  3. IO复用(select)
  4. 异步IO(信号驱动的IO)

IO类型

1、异步通知:一旦设备就绪,则主动通知应用程序。异步通知意味则设备通知自身可访问,实现了异步I/O.由内核向应用程序发信号,类似中断。
2、阻塞I/O意味着一直等待设备可访问后再访问。
3、非阻塞IO,设备不可访问,则马上返回。
4、轮询I/O,使用poll()查询设备是否可访问。

Linux 中最为常见信号的含义及其默认操作,详见Linux信号列表.pdf。

在这里插入图片描述

重点关注的信号:

  • SIGIO 键盘输入或者当文件可读、写
  • SIGINT 终端中断 ctrl+c
  • SIGQUIT 终端退出 ctrl+\

信号实例一

#include <signal.h>
#include <stdio.h>

#include <stdlib.h>
/*自定义信号处理函数*/
void my_func(int sign_no)
{ 
   
    if(sign_no==SIGINT)
    printf("I have get SIGINT\n");
    else if(sign_no==SIGQUIT)
    printf("I have get SIGQUIT\n");
}
int main()
{ 
   
	printf("Waiting for signal SIGINT or SIGQUIT \n ");
	/*发出相应的信号,并跳转到信号处理函数处*/
	signal(SIGINT, my_func);
	signal(SIGQUIT, my_func);
	while(1);
}

信号实例二

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>
#define MAX_LEN 100
/*接收到异步读信号后的动作*/
void input_handler(int signum)
{ 
   	
	char data[MAX_LEN];	
	int len;	
	len=read(STDIN_FILENO,data,MAX_LEN);	
	data[len]=0;	
	printf("input available:%s\n",data);		
}

main()
{ 
   		
	int  oflags;			//启动信号驱动机制 
	signal(SIGIO, input_handler); //让input_handler()处理SIGIO信号 
	fcntl(STDIN_FILENO, F_SETOWN, getpid());		
	oflags = fcntl(STDIN_FILENO, F_GETFL);	
	fcntl(STDIN_FILENO, F_SETFL, oflags | FASYNC);
	while(1);
}

异步IO的实现1

首先在结构体中添加异步结构体指针:

struct globalfifo_dev                                  
{ 
   	
	struct cdev cdev; /*cdev结构体*/                      
	unsigned int current_len;    /*fifo有效数据长度*/	
	unsigned char mem[GLOBALFIFO_SIZE]; /*全局内存*/        
	struct semaphore sem; /*并发控制用的信号量*/ 
	//wait_queue_head_t r_wait; /*阻塞读用的等待队列头*/ 
	//wait_queue_head_t w_wait; /*阻塞写用的等待队列头*/ 
	struct fasync_struct *async_queue; /* 异步结构体指针,用于读 */
};

实现驱动设备的fasync()函数

/* globalfifo fasync函数*/
static int globalfifo_fasync(int fd, struct file *filp, int mode)
{ 
   	
	struct globalfifo_dev *dev = filp->private_data; 	
	return fasync_helper(fd, filp, mode, &dev->async_queue);
}

在相应的资源可以获得的地方添加释放sigio信号,比如在中断,读函数,写函数中,这里举例写函数中:

/*globalfifo写操作*/
static ssize_t globalfifo_write(struct file *filp, const char __user *buf,	size_t count, loff_t *ppos)
{ 
   
	……writeok…..
	/* 产生异步读信号 */		
	if (dev->async_queue)			
	kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
	……
}

在文件关闭时,在release方法将文件从异步通知队列中删除。

/*文件释放函数*/
int globalfifo_release(struct inode *inode, struct file *filp)
{ 
   	
	/* 将文件从异步通知列表中删除 */	
	globalfifo_fasync( - 1, filp, 0);		
	return 0;
}

file_operations中添加fasync函数指针。

/*文件操作结构体*/
static const struct file_operations globalfifo_fops ={ 
   
	.owner = THIS_MODULE,		
	.read = globalfifo_read,		
	.write = globalfifo_write,		
	//.ioctl = globalfifo_ioctl, 
	.poll = globalfifo_poll,		
	.open = globalfifo_open,		
	.release = globalfifo_release,		
	.fasync = globalfifo_fasync,
};

测试程序

void input_handler(int signum)
{ 
   
 相应的处理,比如说程序中异步读通知的话,这里就可以实现读的操作
} 
main()
{ 
   
	int fd, oflags;
	fd = open("dev/fifo, O_RDWR, S_IRUSR | S_IWUSR");
	signal(SIGIO,input_handler);//让input_handler()处理SIGIO信号
	fcntl(fd, F_SETOWN, getpid());//第二个参数的定义是设置异步io所有权,所以这句话的意思是设置本进程为fd文件的所有者
	oflags = fcntl(fd, F_GETFL);//获得文件状态标志
	fcntl(fd, F_SETFL, oflags | FASYNC);//用户程序必须对访问的设备文件设置FASYNC标志。F_SETFL命令表示设置文件状态标志位.
	while(1);
}

今天的文章异步 IO分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8740.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注