* int io_setup ( unsigned nr_events , aio_context_t * ctxp );* int io_destroy ( aio_context_t ctx );* int io_submit ( aio_context_t ctx , long nr , struct iocb * cbp []);* int io_cancel ( aio_context_t ctx , struct iocb *, struct io_event * result );* int io_getevents ( aio_context_t ctx , long min_nr , long nr , struct io_event *events, struct timespec *timeout);
>> aio_context_t.c >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#define _GNU_SOURCE /* syscall() is not POSIX */
#include <stdio.h> /* for perror() */#include <unistd.h> /* for syscall() */#include <sys/syscall.h> /* for __NR_* definitions */#include <linux/aio_abi.h> /* for AIO types and constants */
inline int io_setup ( unsigned nr , aio_context_t * ctxp ){return syscall ( __NR_io_setup , nr , ctxp );}
inline int io_destroy ( aio_context_t ctx ){return syscall ( __NR_io_destroy , ctx );}int main (){aio_context_t ctx ;int ret ;ctx = 0 ;ret = io_setup ( 128 , & ctx );if ( ret < 0 ) {perror ( "io_setup error" );return - 1 ;}printf ( "after io_setup ctx:%Ld\n" , ctx );ret = io_destroy ( ctx );if ( ret < 0 ) {perror ( "io_destroy error" );return - 1 ;}printf ( "after io_destroy ctx:%Ld\n" , ctx );return 0 ;}
typedef unsigned long aio_context_t;
$ gcc - Wall aio_context_t . c - o aio_context_t - laio$ ./ aio_context_tafter io_setup ctx : 139730712117248after io_destroy ctx : 139730712117248
#define _GNU_SOURCE /* syscall() is not POSIX */
#include <stdio.h> /* for perror() */
#include <unistd.h> /* for syscall() */
#include <sys/syscall.h> /* for __NR_* definitions */
#include <linux/aio_abi.h> /* for AIO types and constants */
#include <fcntl.h> /* O_RDWR */
#include <string.h> /* memset() */
#include <inttypes.h> /* uint64_t */
inline int io_setup ( unsigned nr , aio_context_t * ctxp )
{
return syscall ( __NR_io_setup , nr , ctxp );
}
inline int io_destroy ( aio_context_t ctx )
{
return syscall ( __NR_io_destroy , ctx );
}
inline int io_submit ( aio_context_t ctx , long nr , struct iocb ** iocbpp )
{
return syscall ( __NR_io_submit , ctx , nr , iocbpp );
}
inline int io_getevents ( aio_context_t ctx , long min_nr , long max_nr ,
struct io_event * events , struct timespec * timeout )
{
return syscall ( __NR_io_getevents , ctx , min_nr , max_nr , events , timeout );
}
int main ()
{
aio_context_t ctx ;
struct iocb cb ;
struct iocb * cbs [ 1 ];
char data [ 4096 ];
struct io_event events [ 1 ];
int ret ;
int fd ;
int i ;
for ( i = 0 ; i < 4096 ; i ++)
{
data [ i ]= i % 50 + 60 ;
}
fd = open ( "./testfile" , O_RDWR | O_CREAT , S_IRWXU );
if ( fd < 0 ) {
perror ( "open error" );
return - 1 ;
}
ctx = 0 ;
ret = io_setup ( 128 , & ctx );
printf ( "after io_setup ctx:%ld" , ctx );
if ( ret < 0 ) {
perror ( "io_setup error" );
return - 1 ;
}
/* setup I/O control block */
memset (& cb , 0 , sizeof ( cb ));
cb . aio_fildes = fd ;
cb . aio_lio_opcode = IOCB_CMD_PWRITE ;
/* command-specific options */
cb . aio_buf = ( uint64_t ) data ;
cb . aio_offset = 0 ;
cb . aio_nbytes = 4096 ;
cbs [ 0 ] = & cb ;
ret = io_submit ( ctx , 1 , cbs );if ( ret != 1 ) {
if ( ret < 0 )
perror ( "io_submit error" );
else
fprintf ( stderr , "could not sumbit IOs" );
return - 1 ;
}
/* get the reply */
ret = io_getevents ( ctx , 1 , 1 , events , NULL );
printf ( "%d\n" , ret );
struct iocb * result = ( struct iocb *) events [ 0 ]. obj ;
printf ( "reusult:%Ld" , result -> aio_buf );
ret = io_destroy ( ctx );
if ( ret < 0 ) {
perror ( "io_destroy error" );
return - 1 ;
}
return 0 ;
}
1) 每一个提交的IO请求用结构体struct iocb来表示。
首先初始化这个结构体为全零: memset(&cb, 0, sizeof(cb));
然后初始化文件描述符(cb.aio_fildes = fd)和AIO 命令(cb.aio_lio_opcode = IOCB_CMD_PWRITE)
文件描述符对应上文所打开的文件。本例中是./testfile.
内核当前支持的AIO 命令有
IOCB_CMD_PREAD 读; 对应系统调用pread(). IOCB_CMD_PWRITE 写,对应系统调用pwrite(). IOCB_CMD_FSYNC 同步文件数据到磁盘,对应系统调用fsync() IOCB_CMD_FDSYNC 同步文件数据到磁盘,对应系统调用fdatasync()IOCB_CMD_PREADV读,对应系统调用readv() IOCB_CMD_PWRITEV 写,对应系统调用writev()IOCB_CMD_NOOP只是内核使用
cb.aio_buf = (uint64_t)data;其中的data对应要读或要写入的数据的内存地址。
cb.aio_offset=0 表示文件的绝对偏移量
2) 调用io_submit
函数原型int io_submit(aio_context_t ctx, long nr, struct iocb *cbp[]);
当一个IO控制块(struct iocb cb)初始化完毕,把这个指针放入一个数组中( cbs[0] = &cb),因为io_submit系统调用需要接受一个二维指针。在io_submit(ctx, 1, cbs)中, 参数分别为IO上下文(aio_context_t)、数组(struct iocb)大小、数组地址(cbs).
io_submit的返回值,可以是如下值:
A) ret = (提交的iocb的数目)
表示所有的iocb都被接受并处理
B) 0 < ret < (提交的iocb的数目)
io_submit() 系统调用会从传入的cbs中一个一个处理iocb,如果提交的某个iocb失败,将停止并且返回iocb的索引号。没办法知晓错 误的具体原因,但是如果第一个iocb提交失败,参看C条。
C) ret < 0有两种原因:1) 在io_submit()开始之前发生了某种错误(e.g.比如AIO context非法).
2) 提交第一个iocb(cbx[0])失败
3) 调用io_getevents()
当提交了iocb之后,可以不用等待IO完成去做其他的操作。对于每一个已经完成的IO请求(成功或失败),内核都会创建一个io_event结构。io_getevent()系统调用可以用来获取这一结构。这需要做以下操作。
编译并运行:原型 int io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, struct timespec *timeout)a) 使用哪一个AIO上下文(变量ctx)
b) 内核把这个变量放入哪个内存位置 (变量events)
c) events的最小个数(变量min_nr,)如果完成的iocb的个数比这个值要小io_getevents会阻塞,直到达到这个值,
参看第e条查看阻塞时间。
d) 想要获取的events的最大个数(变量nr)。
e) 如果获取不到足够的events,而又不想永久等待。可以指定相对时间(timeout)到最后一个参数,
如果timeout为NULL,表示永久等待。
如果timeout为0,io_getevents()不阻塞 。
$ gcc - Wall submit_reslut . c - o submit_reslut - laio$ ./ submit_reslutafter io_setup ctx : 1404534983884801result : 140735403362480$ cat testfile会发现文中中有相应的内容。
static inline void io_prep_pread(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) static inline void io_prep_pwrite(struct iocb *iocb, int fd, void *buf, size_t count, long long offset) static inline void io_prep_preadv(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset) static inline void io_prep_pwritev(struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt, long long offset) static inline void io_prep_poll(struct iocb *iocb, int fd, int events) static inline void io_prep_fsync(struct iocb *iocb, int fd) static inline void io_prep_fdsync(struct iocb *iocb, int fd) static inline int io_poll(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd, int events) static inline int io_fsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd) static inline int io_fdsync(io_context_t ctx, struct iocb *iocb, io_callback_t cb, int fd) static inline void io_set_eventfd(struct iocb *iocb, int eventfd);