歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> Linux下5種IO模型的小結

Linux下5種IO模型的小結

日期:2017/3/1 9:27:17   编辑:Linux編程
概述

接觸網絡編程,我們時常會與各種與IO相關的概念打交道:同步(Synchronous)、異步(ASynchronous)、阻塞(blocking)和非阻塞(non-blocking)。關於概念的區別看到一位朋友(鏈接)打了一個比較形象的比喻:

你打電話問書店老板有沒有《分布式系統》這本書,如果是同步通信機制,書店老板會說,你稍等,”我查一下",然後開始查啊查,等查好了(可能是5秒,也可能是一天)告訴你結果(返回結果)。
而異步通信機制,書店老板直接告訴你我查一下啊,查好了打電話給你,然後直接掛電話了(不返回結果)。然後查好了,他會主動打電話給你。在這裡老板通過“回電”這種方式來回調。

你打電話問書店老板有沒有《分布式系統》這本書,你如果是阻塞式調用,你會一直把自己“掛起”,直到得到這本書有沒有的結果。如果是非阻塞式調用,你不管老板有沒有告訴你,你自己先一邊去玩了, 當然你也要偶爾過幾分鐘check一下老板有沒有返回結果。

在這裡阻塞與非阻塞與是否同步異步無關。跟老板通過什麼方式回答你結果無關。

同步與異步的主要區別就在於:會不會導致請求進程(或線程)阻塞。同步會使請求進程(或線程)阻塞而異步不會。

linux下有五種常見的IO模型,其中只有一種異步模型,其余皆為同步模型。如圖:

阻塞IO模型

阻塞IO模型是最常見的IO模型了,對於所有的“慢速設備”(socket、pipe、fifo、terminal)的IO默認的方式都是阻塞的方式。阻塞就是進程放棄cpu,讓給其他進程使用cpu。進程阻塞最顯著的表現就是“進程睡眠了”。阻塞的時間通常取決於“數據”是否到來。

非阻塞IO模型

非阻塞IO就是設置IO相關的系統調用為non-blocaking,隨後進行的IO操作無論有沒有可用數據都會立即返回,並設置errno為EWOULDBLOCK或者EAGAIN。我們可以通過主動check的方式(polling,輪詢)確保IO有效時,隨之進行相關的IO操作。當然這種方式看起來就似乎不太靠譜,浪費了太多的CPU時間,用寶貴的CPU時間做輪詢太不靠譜兒了。圖示:

多路復用IO模型

多路復用是讓阻塞發生在我們的多路復用IO操作的系統調用上面,而不是我們真正去執行IO的系統調用。使用這個方式的好處就是可以同時監控多個用於IO的文件描述符。詳細的使用方式之前寫了一篇博客有提到: http://www.linuxidc.com/Linux/2015-07/120335.htm

信號驅動IO模型

所謂信號驅動,就是利用信號機制,安裝信號SIGIO的處理函數(進行IO相關操作),通過監控文件描述符,當其就緒時,通知目標進程進行IO操作(signal handler)。具體使用方法之前博客也有說明:http://www.linuxidc.com/Linux/2015-07/120335.htm

異步IO模型

Linux上異步IO有一組POSIX規定的接口,已aio開頭的幾個SYSCALL。如下:

int aio_read(struct aiocb *aiocbp);

int aio_write(struct aiocb *aiocbp);

ssize_t aio_return(struct aiocb *aiocbp);

使用時記得 Link with -lrt.
參數看起來給人一種很簡潔的假象。其實相較於其他模型的參數一個也沒有少,只是放到了結構體裡邊了。先看一下struct aiocb這個結構的原型吧,頭文件是”aio.h“。
 struct aiocb
{
   int aio_fildes;       /* File desriptor.  */
   int aio_lio_opcode;       /* Operation to be performed.  */
   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];
};

其實雖然結構體足夠長,其實真正用到的也就前面那幾個參數,也沒那麼復雜。具體用法不再贅述。具體可以參考以為網友的博文:http://www.linuxidc.com/Linux/2015-07/120336.htm。

下圖是關於異步IO模型的圖示:

Copyright © Linux教程網 All Rights Reserved