简介
异步IO是计算机程序中处理输入、输出的操作方式,允许程序在等待io操作完成时,不必阻塞当前线程,可以继续执行其他任务。
在异步IO中,当文件描述符可以执行IO操作时,进程请求内核向自己发送一个信号,之后进程就可以执行其他任务,直到文件描述符可以执行I/O操作,内核会给进程发送信号,进程在接收到这个信号之后,执行回调函数,执行对IO的处理。
异步IO相当于是一个软中断,即接收到信号之后,去处理相应内容
使用异步IO
1 使能非阻塞方式打开文件
如果文件是以非阻塞方式打开的,则在打开文件时需要使用O_NONBLOCK标志
fd = open(path, O_RDONLY|O_NONBLOCK);
2 使能O_ASYNC标志
O_ASYNC标志无法通过调用open
函数是直接设置,需要使用fcntl
函数添加该标志
int flag;
flag = fcntl(fd, F_GETFL);
flag |= O_ASYNC;
fcntl(fd, F_SETFL, flag);
3 设置异步事件接收进程
也就是设置异步IO的所有这,内核需要知道将信号发送给哪个进程。
fcntl(fd, F_SETOWN, getpid());
4 注册信号
注册信号可以使用signal()
或者sigaction()
函数注册,函数原型如下:
include <signal.h>
void (*signal(int signo, void (*func)(int))) (int);
sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
signal 函数是一个复杂函数,可以分开来看
函数名:signal
函数参数:int signal, void (*func)(int)
返回值:void (*) (int)
注册默认的SIGIO信号
SIGIO是默认的异步IO信号,可以使用signal()
或者sigaction()
函数注册。还需要一个信号回调函数,用于处理需要执行的IO操作。
static void sigio_handler(int sig)
{
if (sig != SIGIO) { // 信号不正确直接返回
return;
}
xxxx;
}
signal(SIGIO, sigio_handler);
使用实时信号替换默认信号
1)设置使用的信号
fcntl(fd, F_SETSIG, SIGRTMIN);
2)注册信号处理函数
注册实时信号使用sigaction
函数,
struct sigaction act;
act.sa_sigaction = io_handler; // 回调函数
act.sa_flags = SA_SIGINFO;
sigemptyset(&act.sa_mask);
sigaction(SIGRTMIN, &act, NULL);