《VxWorks7编程指南》笔记(十)——I/O系统:异步I/O

目录

VxWorks配置

POSIX AIO函数

AIO控制块

使用AIO

带周期检查完成的AIO

测试AIO完成的其他方法


异步输入输出允许在执行输入输出操作的同时并发地执行原始任务。在任务与I/O操作在逻辑上是相互独立的情况下,可以使用AIO将I/O操作从任务中分离出来。VxWorks的AIO实现符合POSIX1003.1标准。

AIO的可以带来更高的处理效率:它允许在资源可用时进行I/O操作,而不用等待相关事件完成。AIO避免了 同步I/O中的一些不必要的任务阻塞,从而减少了I/O与内部处理之间对资源的竞争,同时也提高了吞吐量。

VxWorks配置

为了使用AIO,需要添加INCLUDE_POSIX_AIO和INCLUDE_POSIX_AIO_SYSDRV组件。第二个组件使能了辅助AIO系统驱动,当前所有的VxWorks设备都需要这个驱动以进行AIO操作。

 

POSIX AIO函数

VxWorks的aioPxLib库提供了POSIX AIO函数。为了异步访问一个文件,可以使用open()函数打开该文件。然后使用open()返回的文件描述符调用AIO函数。POSIX AIO函数(包括两个非POSIX函数)如下表所示:

当VxWorks配置了INCLUDE_POSIX_AIO之后,内核初始化代码将自动条用aioPxLibInit()函数。aioPxInit()函数使用MAX_LIO_CALLS作为其唯一参数。当MAX_LIO_CALLS配置参数被设置为0(默认为0),将会使用AIO_CLUST_MAX宏,该宏的值在privateaioPxLibP.h中定义为100。

当在VxWorks中同时使用了INCLUDE_POSIX_AIO和INCLUDE_POSIX_AIO_SYSDRV组件时,内核函数aioSysInit()函数将自动初始化AIO系统驱动aioSysDrv。aioSysDrv驱动提供了与任何特定设备驱动相独立的请求队列,因此任意VxWorks设备驱动都可以使用AIO。AioSysInit()函数需要有三个参数:待创建的AIO系统任务数、任务优先级、任务栈大小。AIO系统任务数与能够并行处理AIO请求的数量相同。aioSysInit()函数的三个参数由VxWorks的配置参数MAX_AIO_SYS_TASK、AIO_TASK_PRIORTY和AIO_TASK_STACK_SIZE设定。默认情况下,这些配置参数均设置为0,此时实际获取的是宏AIO_IO_TASK_DEFAULT、AIO_IO_PRIO_DELT、AIO_IO_STACK_DELT中定义的值,分别为2,50,0x700。

 

AIO控制块

每个AIO调用都将使用一个AIO控制块(aiocb)作为参数。调用函数必须为aiocb分配空间,在进行AIO操作的过程中,这些空间必须保持有效(除非调用函数不会再AIO操作完成并调用aio_return()之前返回,否则不应该在任务栈中创建aiocb()。每个aiocb描述了一个AIO操作。因此,同时使用同一个aiocb执行AIO操作是无效的,并且会产生未定义的后果。

aiocb结构体在aio.h中定义,包括如下元素:

  • aio_fildes:I/O文件描述符;
  • aio_offset:从文件头部的偏移量;
  • aio_buf:从AIO中读取或存放数据的缓冲区地址;
  • aio_nbytes:读或写的字节数;
  • aio_reqprio:为AIO请求所减少的优先级;
  • aio_sigevent:操作完成时返回的信号(可选);
  • aio_lio_opcode:由lio_listio()函数执行的操作;
  • aio_sys:由VxWorks指定的数据地址(非POSIX)。

使用AIO

函数aio_read()、aio_write()、lio_listio()将初始化AIO操作。lio_listio()函数用于设置可以同时进行异步读写请求的数量。通常,并不是在产生AIO请求后就能立刻用这三个函数完成I/O(读写)初始化。因此,它们的返回值不能反映实际的I/O操作结果,仅仅能够说明一个请求是否成功。

可以使用aio_error()和aio_return()函数获取I/O操作是否成功的信息。

 

带周期检查完成的AIO

如下内核代码使用管道进行AIO操作。示例中创建了一个管道,提交了一个AIO读请求,验证读请求是否还在处理状态中,并提交了一个AIO写请求。在一般情况下,对一个空管道进行同步读的话,将不能够继续执行后续的写操作。但是在AIO中,初始化了读请求后将会继续执行。当写请求提交之后,示例任务将进入循环,周期性地检查AIO请求的状态,直到读写完成为止。因为AIO控制块是在任务栈空间分配的,所以必须在aioExample()函数返回之前调用aio_return()函数。

示例如下:

测试AIO完成的其他方法

一个任务可以通过如下方式确定一个AIO请求是否完成:

  • 像前一个示例中一样,周期性地检查aio_error()的返回值,直到一个AIO请求的状态不再是EINPROGRESS。、
  • 使用aio_suspend()函数将一个任务挂起,直到AIO请求完成。
  • 当AIO请求完毕后,使用信号进行通知。

下面的示例内核代码与之前的aioExample()类似,区别在于它使用了信号来通知写操作的完成。如果从shell进行测试,需要使用比AIO系统任务更低的低优先级创建该任务,以免AIO请求被测试函数阻塞。

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weekman93

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值