《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請求被測試函數阻塞。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章