异步I/O

用的不多,一些概念是模糊的,从网上整理了一些资料。

方法一:使用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

猜你喜欢

转载自onmyway-1985.iteye.com/blog/2115671