搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
小小林熬夜学编程
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
错误:java.lang.NoClassDefFoundError: org/apjache/commons/collections/FastHashMap的解决方法_caused by: java.lang.noclassdeffounderror: lorg/ap
2
few-shot learning是什么_few shot learning是finetune么
3
iwebsec靶场 SQL注入漏洞通关笔记11-16进制编码绕过_sql注入16进制绕过
4
机器学习算法---最小二乘法&&正规方程_最小二乘法正规方程组求解
5
Kaggle数据集快速上传至colab平台,简单快速!保姆级教程!_kaggle cobal
6
uniapp vite 动态修改manifest.json_vite manifest.json
7
openmp 生产者 消费者 实现_openmp程序实现生产和消费的完整代码
8
lgv50进入工程模式_LG手机工程模式进入方法及菜单常用指令
9
windows当打开多个页面时,如何用键盘切换页面焦点?_焦点聚焦到当前窗口 快捷键
10
多线程编程_#pragma omp parallel for
当前位置:
article
> 正文
Linux下原生异步IO接口Libaio的用法_io_set_callback
作者:小小林熬夜学编程 | 2024-03-09 19:12:50
赞
踩
io_set_callback
Linux下原生异步IO接口Libaio的用法
Posted on June 15, 2011 by Jian Zhou
libaio是linux下原生的异步IO接口。网上对其使用方法讨论较少,这里做个简单说明。libaio的使用并不复杂,过程为:libaio的初始化,io请求的下发和回收,libaio销毁。
一、libaio接口
libaio提供下面五个主要API函数:
int io_setup(int maxevents, io_context_t *ctxp);
int io_destroy(io_context_t ctx);
int io_submit(io_context_t ctx, long nr, struct iocb *ios[]);
int io_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt);
int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
五个宏定义:
void io_set_callback(struct iocb *iocb, io_callback_t cb);
void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset);
void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset);
void io_prep_pwritev(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset);
void io_prep_preadv(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset);
这五个宏定义都是操作struct iocb的结构体。struct iocb是libaio中很重要的一个结构体,用于表示IO,但是其结构略显复杂,为了保持封装性不建议直接操作其元素而用上面五个宏定义操作。
二、libaio的初始化和销毁
观察libaio五个主要API,都用到类型为io_context的变量,这个变量为libaio的工作空间。不用具体去了解这个变量的结构,只需要了解其相关操作。创建和销毁libaio分别用到io_setup(也可以用io_queue_init,区别只是名字不一样而已)和io_destroy。
int io_setup(int maxevents, io_context_t *ctxp);
int io_destroy(io_context_t ctx);
三、libaio读写请求的下发和回收
1. 请求下发
libaio的读写请求都用io_submit下发。下发前通过io_prep_pwrite和io_prep_pread生成iocb的结构体,做为io_submit的参数。这个结构体中指定了读写类型、起始扇区、长度和设备标志符。
libaio的初始化不是针对一个具体设备进行初始,而是创建一个libaio的工作环境。读写请求下发到哪个设备是通过open函数打开的设备标志符指定。
2. 请求返回
读写请求下发之后,使用io_getevents函数等待io结束信号:
int io_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout);
io_getevents返回events的数组,其参数events为数组首地址,nr为数组长度(即最大返回的event数),min_nr为最少返回的events数。timeout可填NULL表示无等待超时。io_event结构体的声明为:
struct io_event {
PADDEDptr(void *data, __pad1);
PADDEDptr(struct iocb *obj, __pad2);
PADDEDul(res, __pad3);
PADDEDul(res2, __pad4);
};
其中,res为实际完成的字节数;res2为读写成功状态,0表示成功;obj为之前下发的struct iocb结构体。这里有必要了解一下struct iocb这个结构体的主要内容:
iocbp->iocb.u.c.nbytes 字节数
iocbp->iocb.u.c.offset 偏移
iocbp->iocb.u.c.buf 缓冲空间
iocbp->iocb.u.c.flags 读写
3. 自定义字段
struct iocb除了自带的元素外,还留有供用户自定义的元素,包括回调函数和void *的data指针。如果在请求下发前用io_set_callback绑定用户自定义的回调函数,那么请求返回后就可以显示的调用该函数。回调函数的类型为:
void callback_function(io_context_t ctx, struct iocb *iocb, long res, long res2);
另外,还可以通过iocbp->data指针挂上用户自己的数据。
注意:实际使用中发现回调函数和data指针不能同时用,可能回调函数本身就是使用的data指针。
四、使用例子
通过上面的说明并不能完整的了解libaio的用法,下面通过简单的例子进一步说明。
#include <stdlib.h>
#include <stdio.h>
#include <libaio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libaio.h>
int srcfd = -1;
int odsfd = -1;
#define AIO_BLKSIZE 1024
#define AIO_MAXIO 64
static void wr_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
if (res2 != 0) {
printf("aio write error n");
}
if (res != iocb->u.c.nbytes) {
printf("write missed bytes expect % d got % d n", iocb->u.c.nbytes, res);
exit(1);
}
free(iocb->u.c.buf);
free(iocb);
}
static void rd_done(io_context_t ctx, struct iocb *iocb, long res, long res2)
{
int iosize = iocb->u.c.nbytes;
char *buf = (char *)iocb->u.c.buf;
off_t offset = iocb->u.c.offset;
int tmp;
char *wrbuff = NULL;
if (res2 != 0) {
printf("aio read n");
}
if (res != iosize) {
printf("read missing bytes expect % d got % d", iocb->u.c.nbytes, res);
exit(1);
}
tmp = posix_memalign((void **)&wrbuff, getpagesize(), AIO_BLKSIZE);
if (tmp < 0) {
printf("posix_memalign222 n");
exit(1);
}
snprintf(wrbuff, iosize + 1, "%s", buf);
printf("wrbuff - len = %d:%s n", strlen(wrbuff), wrbuff);
printf("wrbuff_len = %d n", strlen(wrbuff));
free(buf);
io_prep_pwrite(iocb, odsfd, wrbuff, iosize, offset);
io_set_callback(iocb, wr_done);
if (1 != (res = io_submit(ctx, 1, &iocb)))
printf("io_submit write error n");
printf("nsubmit % d write request n", res);
}
void main(int args, void *argv[])
{
int length = sizeof("abcdefg");
char *content = (char *)malloc(length);
io_context_t myctx;
int rc;
char *buff = NULL;
int offset = 0;
int num, i, tmp;
if (args < 3) {
printf("the number of param is wrong n");
exit(1);
}
if ((srcfd = open(argv[1], O_RDWR)) < 0) {
printf("open srcfile error n");
exit(1);
}
printf("srcfd = %d n", srcfd);
lseek(srcfd, 0, SEEK_SET);
write(srcfd, "abcdefg", length);
lseek(srcfd, 0, SEEK_SET);
read(srcfd, content, length);
printf("write in the srcfile successful, content is % s n", content);
if ((odsfd = open(argv[2], O_RDWR)) < 0) {
close(srcfd);
printf("open odsfile error n");
exit(1);
}
memset(&myctx, 0, sizeof(myctx));
io_queue_init(AIO_MAXIO, &myctx);
struct iocb *io = (struct iocb *)malloc(sizeof(struct iocb));
int iosize = AIO_BLKSIZE;
tmp = posix_memalign((void **)&buff, getpagesize(), AIO_BLKSIZE);
if (tmp < 0) {
printf("posix_memalign error n");
exit(1);
}
if (NULL == io) {
printf("io out of memeory n");
exit(1);
}
io_prep_pread(io, srcfd, buff, iosize, offset);
io_set_callback(io, rd_done);
printf("START...n n");
rc = io_submit(myctx, 1, &io);
if (rc < 0)
printf("io_submit read error n");
printf("nsubmit % d read request n", rc);
//m_io_queue_run(myctx);
struct io_event events[AIO_MAXIO];
io_callback_t cb;
num = io_getevents(myctx, 1, AIO_MAXIO, events, NULL);
printf("n % d io_request completed n n", num);
for (i = 0; i < num; i++) {
cb = (io_callback_t) events[i].data;
struct iocb *io = events[i].obj;
printf("events[%d].data = %x, res = %d, res2 = %d n", i, cb, events[i].res, events[i].res2);
cb(myctx, io, events[i].res, events[i].res2);
}
}
声明:
本文内容由网友自发贡献,转载请注明出处:
【wpsshop】
推荐阅读
article
linux
c
嵌入式
工程师
笔试题,
嵌入式
软件
工程师
/
linux
c
程序员 笔试题...
一、什么叫可重入?可重入函数主要用于多任务环境中,一个可重入的函数简单来说就是可以被中断的函数,也就是说,可以在这个函数...
赞
踩
article
linux
编译
mqtt
静态库,无法为
arm
-
none
-
linux
-
gnueabi
-g ++编译器找...
I have the
arm
-
none
-
linux
-
gnueabi
-g++ compiler in the below ...
赞
踩
article
linux
下解决
qt
项目
error
while
loading
shared
libraries: ...
linux
下运行
qt
项目,能编译通过,但不能运行出应用程序_./
qt
-
unified
-
linux
-x64-4.6.1-o...
赞
踩
article
Mysql出现问题:mysqld:
error
while
loading
shared
libra...
mysql问题库及解决方案_
error
while
loading
shared
libraries
:
libaio
.s...
赞
踩
article
ubuntu
在线安装qt碰到的问题及解决_./qt-
unified
-
linux
-
x64
-4.6.1-...
ubuntu
中在线安装qt碰到的问题。_./qt-
unified
-
linux
-
x64
-4.6.1-
online
.
run
:...
赞
踩
article
Ubuntu安装QT:
error
whi
le
loading
shared
libraries: l...
【代码】Ubuntu安装QT:
error
whi
le
loading
shared
libraries:
libxcb
-...
赞
踩
article
解决
dbus
-
1
.
so.3
: no
version
information available 造成...
删除错误的lib
dbus
-
1
.
so.3
快捷方式,并将正确的lib
dbus
-
1
.
so.3
.XX.X拷贝到usr/lib64...
赞
踩
article
解决问题:
libbz2
.so.1: cannot open
shared
object
file
:...
解决缺少
libbz2
.so.1文件的问题。
err
or
while
loading
shared
libraries: l...
赞
踩
article
ubuntu
Linux
安装QT_qt-
unified
-
linux
-x64-4.6.1-
online
...
ubuntu
Linux
安装QT下载开源QT
Linux
安装包地址https://www.qt.io/download-o...
赞
踩
article
Linux
Qt6
安装
教程及错误解决_
ubuntu
安装
qt6
...
在
Linux
环境,通常为Ubuntu,
安装
Qt开发环境,
安装
教程以及遇到的错误解决_
ubuntu
安装
qt6
ubuntu
...
赞
踩
article
Ubuntu
安装Qt出现
bash
: ./
qt
-
unified
-
linux
-x64-
4.6
.1-onl...
Ubuntu
安装Qt出现
bash
: ./
qt
-
unified
-
linux
-x64-
4.6
.1-
online
.
run
: 权...
赞
踩
article
linux
ubuntu安装
qt
creater,配置
qt
环境到可运行
qt
项目_./
qt
-unifie...
一、安装
qt
creater1、搜索清华源,打开路径到
qt
位置,选择第二个文件,下载下来2、打开下载路径,执行chmod ...
赞
踩
article
linux
下
C++
#
include
的
搜索
路径
问题_
linux
include
搜索
路径
...
Linux c++_
linux
include
搜索
路径
linux
include
搜索
路径
...
赞
踩
article
linux
c
之g
c
c
编译出现error:
lvalue
required
as
unary
‘&‘ ...
1、问题 今天搞epoll实现io复用的时候g
c
c
编译出现这个错误
lvalue
required
as
unary
'&...
赞
踩
article
linux
使用
gcc
提示
后缀
无效
,
linux
– Gcc
编译
“无法计算对象文件的
后缀
:无法
编译
”.....
我实际上正在阅读LFS书(7.1版)
,
我在第53页被阻止.尝试
编译
gcc
,
我尝试了以下命令:./configure --...
赞
踩
article
arm
-
linux
-
gnueabihf
-gcc 5.2编译qt4.8.5_
dialogs
/qprin...
arm
-
linux
-
gnueabihf
-gcc 5.2编译qt4.8.5_
dialogs
/
qprintdialog
_un...
赞
踩
article
linux
signal
编译
不过,
Linux
编译
中
的各种
error
处理...
LDD3
中
的第一个例程就是scull,但是在新内核上
编译
的过程那叫一个坎坷。。。在此做出总结,希望可以帮到同路人。。。一...
赞
踩
article
【
FastDFS
】小伙伴们说按照我写的方式在
CentOS
8
服务器
上搭建
FastDFS
环境总报错?_...
这下在
CentOS
8
服务器
上
安装
FastDFS
不会报错了吧!_
c
entos
安装
fastdfs4.0
.6
c
ommon
...
赞
踩
article
Linux
学习
笔记(
12
)...
acpid 否 监听精灵进程 此进程监听并分配内核中的 acpi 事件adsl 否 内部 ADSL 开关控制 只...
赞
踩
article
Linux
:修改
文件
权限...
在
Linux
系统中,权限管理是
文件
和目录安全性的核心。
文件
权限是非常重要的,它们决定了哪些用户可以读取、写入或执行
文件
。...
赞
踩
相关标签
linux c嵌入式工程师笔试题
linux 编译mqtt静态库
linux
qt
mysql
centos
1024程序员节
ubuntu
运维
开发语言
qtcreator
qt5
installer
UOS
bash
权限