用的不多,一些概念是模糊的,从网上整理了一些资料。
方法一:使用fcntl来置O_ASYNC位。
这个方法的效果是,当输入缓存中的输入数据就绪时(输入数据
可读),内核向用F_SETOWN来绑定的那个进程发送SIGIO信号。此时程序应该用getchar等函数将输入读入。
1.首先,为SIGIO信号设置一个处理函数,用来读取并处理位于输入缓存中的数据。
signal ( SIGIO , void ( * getmyinput ) ( int signum ) );
2.设置一个用来接受SIGIO信号的进程。用fcntl函数。
fcntl ( my_fd , F_SETOWN, getpid() );
3.得到文件描述符的状态标志集,为该状态标志集添加一个O_ASYNC属性。
int flags = fcntl ( my_fd , F_GETFL);
fcntl ( my_fd , F_SETFL , flags | O_ASYNC);
第二种方法:使用 aio_read() 方法—— <aio.h>
air_read是异步非阻塞IO,是一种处理与I/O 重叠进行的模型。读请求(aio_read())会立即返回,说明读请求已经成功发起了。在后台完成读操作的同时时,应用程序然后会执行其他处理操作。当read的响应到达时,就会产生一个信号或执行一个基于线程的回调函数来完成这次 I/O 处理过程。
类似于处理器三级指令流水线。在一个进程中为了执行"多个I/O 请求"而对"计算操作"和 "I/O处理"进行重叠处理的能力.
与O_ASYNC方法不同,aio_read()方法更复杂也更灵活,它可以控制每次想要读取的字节数,也可以控制当满足读取要求的字节数来到时,向进程发送的信号。
通过一个中间变量 struct aiocb 来作为缓存。、
当进程收到SIGIO信号,或其在aiocb.aio_sigevent.sigev_signo已经设置好的信号时,内核已经将输入读入到了指针aiocb.aio_buf 所指定的位置中了。
API 函数 说明
aio_read 请求异步读操作
aio_error 检查异步请求的状态
aio_return 获得完成的异步请求的返回状态
aio_write 请求异步写操作
aio_suspend 挂起调用进程,直到一个或多个异步请求已经完成(或失败)
aio_cancel 取消异步 I/O 请求
lio_listio 发起一系列 I/O 操作
aiocb结构体:
struct aiocb
{
int aio_fildes; /* File desriptor. */
int aio_lio_opcode; /* Operation to be performed,Valid only for lio_listio (r/w/nop)*/
int aio_reqprio; /* Request priority offset. */
volatile void *aio_buf; /* Location of buffer. */
size_t aio_nbytes; /* Length of transfer. */
struct sigevent aio_sigevent; /* Signal number and value. */
/* 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];
};
两段代码例子:
#include <aio.h>
...
int fd, ret;
struct aiocb my_aiocb;
fd = open( "file.txt", O_RDONLY );
if (fd < 0) perror("open");
/* Zero out the aiocb structure (recommended) */
bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
/* Allocate a data buffer for the aiocb request */
my_aiocb.aio_buf = malloc(BUFSIZE+1);
if (!my_aiocb.aio_buf) perror("malloc");
/* Initialize the necessary fields in the aiocb */
my_aiocb.aio_fildes = fd;
my_aiocb.aio_nbytes = BUFSIZE;
my_aiocb.aio_offset = 0;
ret = aio_read( &my_aiocb );
if (ret < 0) perror("aio_read");
while ( aio_error( &my_aiocb ) == EINPROGRESS ) ;
if ((ret = aio_return( &my_iocb )) > 0) {
/* got ret bytes on the read */
} else {
/* read failed, consult errno */
}
使用信号作为 AIO 请求的通知:
void setup_io( ... )
{
int fd;
struct sigaction sig_act;
struct aiocb my_aiocb;
...
/* Set up the signal handler */
sigemptyset(&sig_act.sa_mask);
sig_act.sa_flags = SA_SIGINFO;
sig_act.sa_sigaction = aio_completion_handler;
/* Set up the AIO request */
bzero( (char *)&my_aiocb, sizeof(struct aiocb) );
my_aiocb.aio_fildes = fd;
my_aiocb.aio_buf = malloc(BUF_SIZE+1);
my_aiocb.aio_nbytes = BUF_SIZE;
my_aiocb.aio_offset = next_offset;
/* Link the AIO request with the Signal Handler */
my_aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
my_aiocb.aio_sigevent.sigev_signo = SIGIO;
my_aiocb.aio_sigevent.sigev_value.sival_ptr = &my_aiocb;
/* Map the Signal to the Signal Handler */
ret = sigaction( SIGIO, &sig_act, NULL );
...
ret = aio_read( &my_aiocb );
}
void aio_completion_handler( int signo, siginfo_t *info, void *context )
{
struct aiocb *req;
/* Ensure it's our signal */
if (info->si_signo == SIGIO) {
req = (struct aiocb *)info->si_value.sival_ptr;
/* Did the request complete? */
if (aio_error( req ) == 0) {
/* Request completed successfully, get the return status */
ret = aio_return( req );
}
}
return;
}
参考:
http://www.ibm.com/developerworks/cn/linux/l-async/
http://www.cnblogs.com/hustcat/archive/2010/04/10/1708909.html
http://blog.csdn.net/wenhuiqiao/article/details/7066267