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

news/2025/2/22 23:44:17/

文章目录

  • 前言
  • 异步IO示例
  • 带回调的异步IO
  • 使用aio_read的echo服务
  • 总结


前言

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>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);} 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);write(cb->aio_fildes, 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 = malloc(sizeof(struct aiocb));buf = 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;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(9999);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;
}

总结


http://www.ppmy.cn/news/1254540.html

相关文章

Hdoop学习笔记(HDP)-Part.19 安装Kafka

目录 Part.01 关于HDP Part.02 核心组件原理 Part.03 资源规划 Part.04 基础环境配置 Part.05 Yum源配置 Part.06 安装OracleJDK Part.07 安装MySQL Part.08 部署Ambari集群 Part.09 安装OpenLDAP Part.10 创建集群 Part.11 安装Kerberos Part.12 安装HDFS Part.13 安装Ranger …

网站有必要使用SSL证书吗

随着互联网的快速发展&#xff0c;网络安全问题也变得日益突出&#xff0c;SSL证书的作用日益凸显。 什么是SSL证书&#xff1f; SSL证书&#xff08;Secure Sockets Layer Certificate&#xff09;&#xff0c;也称为TLS证书&#xff08;Transport Layer Security Certifica…

【C/C++笔试练习】公有派生、构造函数内不执行多态、抽象类和纯虚函数、多态中的缺省值、虚函数的描述、纯虚函数的声明、查找输入整数二进制中1的个数、手套

文章目录 C/C笔试练习选择部分&#xff08;1&#xff09;公有派生&#xff08;2&#xff09;构造函数内不执行多态&#xff08;3&#xff09;抽象类和纯虚函数&#xff08;4&#xff09;多态中的缺省值&#xff08;5&#xff09;程序分析&#xff08;6&#xff09;重载和隐藏&a…

3.3 路由器的远程配置

实验3.3 路由器的远程配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施&#xff08;一&#xff09;、配置通过Telnet登录系统1.RA的基本配置2.RB的基本配置3.在RA上配置Telnet用户登录界面 &#xff08;二&#xff09;、配置通过STelnet登录系统1.RA的基本配…

【从删库到跑路 | MySQL总结篇】事务详细介绍

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、事务…

supervisor管理启动重启,Java,Go程序Demo

简介 Supervisor 是一款 Python 开发的进程管理系统&#xff0c;允许用户监视和控制 Linux 上的进程&#xff0c;能将一个普通命令行进程变为后台守护进程&#xff0c;异常退出时能自动重启 1、安装 yum -y install supervisor2、配置默认配置文件 echo_supervisord_conf &g…

使用wininet下载一个网页

WinInet基础知识 | Microsoft Learn //this code excerpt also demonstrates try/catch exception handling #include <afxinet.h> void DisplayHttpPage(LPCTSTR pszServerName, LPCTSTR pszFileName) { CInternetSession session(_T("My Session")); …

Android Wifi的扫描机制

Android Wifi 的扫描场景分为下面四种情况&#xff1a; 1.亮屏情况下&#xff0c;在Wifi settings界面&#xff0c;固定扫描&#xff0c;扫描时间为10s。 2.亮屏情况下&#xff0c;在非Wifi settings界面&#xff0c;二进制指数退避扫描&#xff0c;退避&#xff1a;interval…