C/C++ Linux 异步IO(AIO)

1.select和poll

IO多路转换技术, select, poll的原理是: 通过将待监听文件描述符(fd)加入集合, 然后通过查询其调用返回值, 取得数据有动静的fd数量, 再轮询集合中每个fd, 如果有数据, 就直接读取; 如果没有数据, 就等待下一次查询.
select和poll实现了异步形式通知, 但本质上还是需要主动轮询.

2. BSD异步IO

System V和BSD都有一套各自的异步IO, 原理类似, 这里只介绍BSD异步IO.
BSD异步IO是信号SIGIO, SIGURG的组合: SIGIO 通用异步IO信号; SIGURG 用来通知进程网络连接上的带外数据(data of band, 紧急数据)已经达到.

进程接收SIGIO信号, 需要执行的步骤:

  1. 调用signal/sigaction为SIGIO信号建立处理程序;
  2. 调用fcntl, 命令参数F_SETOWN, 设置进程ID或进程组ID, 用于告诉驱动程序/内核, 指定进程接收SIGIO信号;
  3. 调用fcntl, 命令参数F_SETFL, 设置O_ASYNC文件状态标识, 以便在该fd上可以进行异步IO;

进程接收SIGURG, 只需只需第1,2步. 信号仅对引用支持带外数据的网络连接描述符 产生, 如TCP连接(UDP不支持).

BSD异步IO例程
完整源代码, 请参见 async.c
关键步骤代码

void sig_fun() {
    int data = 0;
    int n = read(mousefd, &data, sizeof(data));
    if (n < 0) {
        printf("read mouse error\n");
    }
    else {
        printf("%d\n", data);
    }
}

struct sigaction sa;
struct sigaction od_sa;

sa.sa_handler = sig_fun;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGIO); // SIGIO添加进信号集
sa.sa_flags = 0;

// 1. 调用sigaction为SIGIO信号建立信号处理程序
sigaction(SIGIO, &sa, &od_sa); // 捕获SIGIO后, 处理信号时, 阻塞信号; 处理完毕后恢复

// 2. 以命令F_SETOWN调用fcntl来设置进程ID, 用于接收对该描述符的信号(SIGIO)
if (fcntl(mousefd, F_SETOWN, getpid()) < 0) {
    perror("fcntl F_SETOWN error");
    exit(1);
}

// 3. 以命令F_SETFL调用fcntl, 设置O_ASYNC文件状态标识, 使得在该描述符上可以进行异步IO
int flag = fcntl(mousefd, F_GETFL);
if (flag < 0) {
    perror("fcntl F_GETFL error");
    exit(1);
}
flag |= O_ASYNC;

ret = fcntl(mousefd, F_SETFL, flag);
if (ret < 0) {
    perror("fcntl F_SETFL error");
    exit(1);
}

while (1) {
    usleep(50);
}

3. POSIX异步IO(AIO)

BSD对不同的设备文件进行异步IO方法不一样, 如终端设备是产生SIGIO信号, 仅支持带外数据的设备才能产生SIGURG信号.
POSIX对不同类型文件进

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值