IO分类
- 阻塞IO
- 非阻塞IO
- IO复用(select)
- 异步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