4-POSIX 异步IO(批量请求)

POSIX 提供了函数 lio_listio 可以让我们一次性发起多个异步 IO 请求。

1. lio_listio

(1) 函数原型

int lio_listio(int mode, struct aiocb *const aiocb_list[], int nitems, struct sigevent *sevp);

(2) 函数参数

  • mode

mode 有两个可选值:LIO_WAIT 和 LIO_NOWAIT.

含义
LIO_WAIT lio_listio 会阻塞,直到所有的异步 IO 请求完成。此时参数 sevp 被忽略掉
LIO_NOWAIT lio_listio 会立即返回,当所有异步 IO 请求完成后,会进行异步通知,通知的方式由参数 sevp 指定,该参数可以为 NULL,表示不需要异步通知。通知方式我们在下一讲就会说了。

  • aiocb_list 和 nitems
struct aiocb {
  /* 下面所有字段依赖于具体实现 */

  int             aio_fildes;     /* 文件描述符 */
  off_t           aio_offset;     /* 文件偏移 */
  volatile void  *aio_buf;        /* 缓冲区地址 */
  size_t          aio_nbytes;     /* 传输的数据长度 */
  int             aio_reqprio;    /* 请求优先级 */
  struct sigevent aio_sigevent;   /* 通知方法 */
  int             aio_lio_opcode; /* 仅被 lio_listio() 函数使用 */

  /* Various implementation-internal fields not shown */
};

      aiocb_list 就是 aiocb 结构体指针的数组,nitems 参数表示数组的大小。在使用 lio_listio 函数时,需要将 aiocb 中的 aio_lio_opcode 成员赋值,所以到这里,我们又学习到了一个新的成员。该成员告诉内核发起的是何中异步 IO 操作。aio_lio_opcode 的值可以为下面这些:

含义
LIO_READ 发起异步读操作
LIO_WRITE 发起异步写操作
LIO_NOP 表示忽略掉该 aiocb

还有最后一个参数,这里我们先不考虑它,在使用 lio_listio 函数的时候,将 sevp 设置为 NULL 就行了。

2. 实验

       修改了前面的代码,将 aio_read 函数替换成了 lio_listio 函数发起异步读请求。程序中并没有演示同时发起多个请求,只是发起了一个。实际上,一个你会了,多个也没什么问题,无非就是给数组赋几个值而已。

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <aio.h>
#include <strings.h>
#include <errno.h>

#define ERR_EXIT(msg) do { perror(msg); exit(1); } while(0)

int main() {
  int fd, ret;
  char buf[64];
  // 定义一个异步控制块结构体,不懂没关系,不用管
  struct aiocb my_aiocb;

  // 初始化
  bzero((char*)&my_aiocb, sizeof(struct aiocb));

  my_aiocb.aio_buf = buf; // 告诉内核,有数据了就放这儿
  my_aiocb.aio_fildes = STDIN_FILENO; // 告诉内核,想从标准输入读数据
  my_aiocb.aio_nbytes = 64; // 告诉内核,缓冲区大小只有 64
  my_aiocb.aio_offset = 0; // 告诉内核,从偏移为 0 的地方开始读
  //注意这里多了一个成员的赋值,aio_lio_opcode成员是专门给lio_listio函数使用的
  my_aiocb.aio_lio_opcode=LIO_READ;
  
  struct aiocb *aio_list[5]={NULL};
  
  aio_list[2]=&my_aiocb;
  
  //调用lio_listio发起读请求
  ret=lio_listio(LIO_NOWAIT,aio_list,5,NULL);
  
  while(aio_error(&my_aiocb) == EINPROGRESS) {
       write(STDOUT_FILENO,".",1);
	   sleep(1);
  }

  printf("content: %s\n", buf);

  return 0;
  
}

 编译与运行

           

                                                                                图一运行结果

            程序启动后,在屏幕上开始打点,不用管它,直接输入 hello 然后回车。

3. 总结

  • 掌握 lio_listio 函数

3-POSIX异步IO(等待异步操作)

5-POSIX 异步IO(异步通知)

转自:https://blog.csdn.net/q1007729991/article/details/68064840

猜你喜欢

转载自blog.csdn.net/m0_37806112/article/details/82312772