异步I/O操作函数aio_xxx函数

本文介绍了POLLUX库中的异步I/O函数,如aio_read、aio_write等,并展示了如何在回调和线程上下文中使用它们,以及在echo服务中的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

POXSIX提供了用于异步I/O的"aio_xxx"函数集。

名称功能
aio_read异步read
aio_write异步write
aio_fsync异步fsync
aio_error获取错误状态
aio_return获取返回值
aio_cancel请求取消
aio_suspend请求等待

异步IO示例

#include <aio.h>

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

int main(int argc, char* argv[])
{
    if (argc < 2) return 1;
    struct aiocb cb;
    const struct aiocb* cblist[1];
    char buf[BUFSIZ];
    int fd, n;

    fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    memset(&cb, 0, sizeof(struct aiocb));
    cb.aio_fildes = fd;
    cb.aio_buf = buf;
    cb.aio_nbytes = BUFSIZ-1;

    n = aio_read(&cb);
    if (n < 0) {
        perror("aio_read");
        exit(EXIT_FAILURE);
    }
    cblist[0] = &cb;
    n = aio_suspend(cblist, 1, NULL);
    if (n != 0) {
        perror("aio_read");
        exit(EXIT_FAILURE);
    }
    n = aio_return(&cb);
    if (n < 0) {
        perror("aio_return");
        exit(EXIT_FAILURE);
    }
    buf[n] = '\0';
    printf("%s\n", buf);
    return 0;
}

将aio_read, aio_suspend, aio_return 放在循环中时不能正确读取内容超过缓冲区大小的内容

带回调的异步IO

在回调函数的调用上,有信号和线程两种方式,下面时使用线程进行回调的方式。
如果用SIGEV_THREAD设置回调函数并调用aio_read,从系统内部来看,实际上是用多个线程来实现异步IO。

#include <aio.h>
// #include <asm-generic/siginfo.h>

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

static void read_done(__sigval_t sigval)
{
    struct aiocb *cb;
    int n;
    cb = (struct aiocb*)(sigval.sival_ptr);
    if (aio_error(cb)  == 0)
    {
        n = aio_return(cb);
        if (n < 0)
        {
            perror("aio_return");
            exit(EXIT_FAILURE);
        }
        printf("%d %d ---\n%.*s", n, cb->aio_nbytes, cb->aio_nbytes, cb->aio_buf);
        exit(EXIT_SUCCESS);
    }
    return;
}

int main(int argc, char* argv[])
{
    if (argc < 2) return 1;
    struct aiocb cb;
    char buf[BUFSIZ] = {'\0'};
    int fd, n;

    fd = open(argv[1], O_RDONLY);
    if (fd < 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    memset(&cb, 0, sizeof(struct aiocb));
    cb.aio_fildes = fd;
    cb.aio_buf = buf;
    cb.aio_nbytes = BUFSIZ-1;
    cb.aio_sigevent.sigev_notify = SIGEV_THREAD;
    cb.aio_sigevent.sigev_notify_function = &read_done;
    cb.aio_sigevent.sigev_value.sival_ptr = &cb;

    n = aio_read(&cb);
    if (n < 0) {
        perror("aio_read");
        exit(EXIT_FAILURE);
    }
    
    select(0, NULL, NULL, NULL, NULL);
    return 0;
}

使用aio_read的echo服务


#include <aio.h>
// #include <asm-generic/siginfo.h>

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>

#include <vector>

static void read_done(__sigval_t sigval)
{
    printf("read done tid: %d\n", gettid());
    struct aiocb *cb;
    int n;
    cb = (struct aiocb*)(sigval.sival_ptr);
    if (aio_error(cb)  == 0)
    {
        n = aio_return(cb);
        if (n < 0)
        {
            perror("aio_return");
            exit(EXIT_FAILURE);
        } else if (0 == n) {
            printf("client %d gone\n", cb->aio_fildes);
            aio_cancel(cb->aio_fildes, cb);
            close(cb->aio_fildes);
            free(cb);
            return;
        }
        printf("client %d (%d)\n", cb->aio_fildes, n);
        
        std::vector<char> buf(n+1, 0);
        memcpy(buf.data(), (void*)cb->aio_buf, n);
        printf("[%s]\n", buf.data());

        write(cb->aio_fildes, (void*)cb->aio_buf, n);
        aio_read(cb);
    }
    else
    {
        printf("aio_error\n");
    }
    return;
}
static void register_read(int fd)
{
    struct aiocb *cb;
    char* buf;
    printf("client register %d\n", fd);
    cb = ( struct aiocb *)malloc(sizeof(struct aiocb));
    buf = (char*)malloc(BUFSIZ);
    memset(cb, 0, sizeof(struct aiocb));
    cb->aio_fildes = fd;
    cb->aio_buf = buf;
    cb->aio_nbytes = BUFSIZ;
    cb->aio_sigevent.sigev_notify = SIGEV_THREAD;  // 每次以创建新线程的方式呼叫回调函数
    cb->aio_sigevent.sigev_notify_function = read_done;
    cb->aio_sigevent.sigev_value.sival_ptr = cb;//
    if (aio_read(cb) != 0)
    {
        perror("aio_read");
        return;
    }
}
int main(int argc, char* argv[])
{
    if (argc < 2) return 1;
    printf("pid: %d\n", gettid());
    struct sockaddr_in addr;
    int s = socket(PF_INET, SOCK_STREAM, 0);

    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(9998);
    if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
        perror("bind");
        exit(EXIT_FAILURE);
    }
    listen(s, 5);
    for (;;)
    {
        int c = accept(s, NULL, 0);
        if (c < 0) continue;
        register_read(c);
    }
    return 0;
}

总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值