linux aio进程简介,Linux AIO机制

Linux的I/O机制经历了一下几个阶段的演进:

1. 同步阻塞I/O: 用户进程进行I/O操作,一直阻塞到I/O操作完成为止。

2. 同步非阻塞I/O: 用户程序可以通过设置文件描述符的属性O_NONBLOCK,I/O操作可以立即返回,但是并不保证I/O操作成功。

3. 异步事件阻塞I/O: 用户进程可以对I/O事件进行阻塞,但是I/O操作并不阻塞。通过select/poll/epoll等函数调用来达到此目的。

4. 异步时间非阻塞I/O: 也叫做异步I/O(AIO),用户程序可以通过向内核发出I/O请求命令,不用等带I/O事件真正发生,可以继续做另外的事情,等I/O操作完成,内核会通过函数回调或者信号机制通知用户进程。这样很大程度提高了系统吞吐量。

下面就AIO做详细介绍:

要使用aio的功能,需要include头文件aio.h,在编译连接的时候需要加入POSIX实时扩展库rt.下面就aio库的使用做介绍。

1. AIO整个过程所使用的数据存放在一个结构体中,struct aiocb,aio control block.看看头文件中的定义:

/* Asynchronous I/O control block.  */

struct aiocb

{

int aio_fildes;              /* File desriptor.  */ 需要在哪个文件描述符上进行I/O

int aio_lio_opcode;          /* Operation to be performed.  */ 这个是针对批量I/O的情况有效,读写操作类型

int aio_reqprio;              /* Request priority offset.  */ 请求优先级(If  _POSIX_PRIORITIZED_IO  is defined, and this file supports it, then the

asynchronous operation is submitted at a priority equal to that of the

calling process minus aiocbp->aio_reqprio.)

volatile void *aio_buf;      /* Location of buffer.  */ 具体内容,数据缓存

size_t aio_nbytes;            /* Length of transfer.  */ 数据缓存的长度

struct sigevent aio_sigevent; /* Signal number and value.  */ 用于异步I/O完成后的通知。

内部实现使用的数据成员。

/* Internal members.  */

struct aiocb *__next_prio;

int __abs_prio;

int __policy;

int __error_code;

__ssize_t __return_value;

#ifndef __USE_FILE_OFFSET64

__off_t aio_offset;          /* File offset.  */

char __pad[sizeof (__off64_t) - sizeof (__off_t)];

#else

__off64_t aio_offset;        /* File offset.  */ 文件读写偏移

#endif

char __unused[32];

};

2. int aio_read(struct aiocb *aiocbp);

异步读操作,向内核发出读的命令,传入的参数是一个aiocb的结构,比如

struct aiocb myaiocb;

memset(&aiocb , 0x00 , sizeof(myaiocb));

myaiocb.aio_fildes = fd;

myaiocb.aio_buf = new char[1024];

myaiocb.aio_nbytes = 1024;

if (aio_read(&myaiocb) != 0)

{

printf("aio_read error:%s/n" , strerror(errno));

return false;

}

3. int aio_write(struct aiocb *aiocbp);

异步写操作,向内核发出写的命令,传入的参数仍然是一个aiocb的结构,当文件描述符的O_APPEND

标志位设置后,异步写操作总是将数据添加到文件末尾。如果没有设置,则添加到aio_offset指定的

地方,比如:

struct aiocb myaiocb;

memset(&aiocb , 0x00 , sizeof(myaiocb));

myaiocb.aio_fildes = fd;

myaiocb.aio_buf = new char[1024];

myaiocb.aio_nbytes = 1024;

myaiocb.aio_offset = 0;

if (aio_write(&myaiocb) != 0)

{

printf("aio_read error:%s/n" , strerror(errno));

return false;

}

4. int aio_error(const struct aiocb *aiocbp);

如果该函数返回0,表示aiocbp指定的异步I/O操作请求完成。

如果该函数返回EINPROGRESS,表示aiocbp指定的异步I/O操作请求正在处理中。

如果该函数返回ECANCELED,表示aiocbp指定的异步I/O操作请求已经取消。

如果该函数返回-1,表示发生错误,检查errno。

5. ssize_t aio_return(struct aiocb *aiocbp);

这个函数的返回值相当于同步I/O中,read/write的返回值。只有在aio_error调用后

才能被调用。

6. int aio_cancel(int fd, struct aiocb *aiocbp);

取消在文件描述符fd上的aiocbp所指定的异步I/O请求。

如果该函数返回AIO_CANCELED,表示操作成功。

如果该函数返回AIO_NOTCANCELED,表示取消操作不成功,使用aio_error检查一下状态。

如果返回-1,表示发生错误,检查errno.

7. int lio_listio(int mode, struct aiocb *restrict const list[restrict],

int nent, struct sigevent *restrict sig);

使用该函数,在很大程度上可以提高系统的性能,因为再一次I/O过程中,OS需要进行

用户态和内核态的切换,如果我们将更多的I/O操作都放在一次用户太和内核太的切换中,

减少切换次数,换句话说在内核尽量做更多的事情。这样可以提高系统的性能。

用户程序提供一个struct aiocb的数组,每个元素表示一次AIO的请求操作。需要设置struct aiocb

中的aio_lio_opcode数据成员的值,有LIO_READ,LIO_WRITE和LIO_NOP。

nent表示数组中元素的个数。最后一个参数是对AIO操作完成后的通知机制的设置。

8. 设置AIO的通知机制,有两种通知机制:信号和回调

(1).信号机制

首先我们应该捕获SIGIO信号,对其作处理:

struct sigaction sig_act;

sigempty(&sig_act.sa_mask);

sig_act.sa_flags = SA_SIGINFO;

sig_act.sa_sigaction = aio_handler;

struct aiocb myaiocb;

bzero( (char *)&myaiocb, sizeof(struct aiocb) );

myaiocb.aio_fildes = fd;

myaiocb.aio_buf = malloc(BUF_SIZE+1);

myaiocb.aio_nbytes = BUF_SIZE;

myaiocb.aio_offset = next_offset;

myaiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;

myaiocb.aio_sigevent.sigev_signo = SIGIO;

myaiocb.aio_sigevent.sigev_value.sival_ptr = &myaiocb;

ret = sigaction( SIGIO, &sig_act, NULL );

信号处理函数的实现:

void aio_handler( int signo, siginfo_t *info, void *context )

{

struct aiocb *req;

if (info->si_signo == SIGIO) {

req = (struct aiocb *)info->si_value.sival_ptr;

if (aio_error( req ) == 0) {

ret = aio_return( req );

}

}

return;

}

(2). 回调机制

需要设置:

myaiocb.aio_sigevent.sigev_notify = SIGEV_THREAD

my_aiocb.aio_sigevent.notify_function = aio_handler;

回调函数的原型:

typedef void (* FUNC_CALLBACK)(sigval_t sigval);

AIO机制为服务器端高并发应用程序提供了一种性能优化的手段。加大了系统吞吐量。

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值