什么是I/O復用?
What we need is the capability to tell the kernel that we want to be notified if one or more I/O conditions are ready (i.e., input is ready to be read, or the descriptor is capable of taking more output). This capability is called I/O multiplexing and is provided by the select and poll functions. ——來自《Unix網絡編程》第三卷
在很多情況下,使用select或是poll,可以把事件的響應交給底層操作系統來管理,當有I/O事件發生時,操作系統會通知我們。
何時使用I/O復用:
1、When a client is handling multiple descriptors (normally interactive input and a network socket), I/O multiplexing should be used. This is the scenario we described previously.
2、It is possible, but rare, for a client to handle multiple sockets at the same time. We will show an example of this using select in Section 16.5 in the context of a Web client.
3、If a TCP server handles both a listening socket and its connected sockets, I/O multiplexing is normally used.
4、If a server handles both TCP and UDP, I/O multiplexing is normally used.
5、If a server handles multiple services and perhaps multiple protocols, I/O multiplexing is normally used.
——來自《Unix網絡編程》第三卷
I/O模型
對于read而言,一般都會涉及到兩個過程:
1. Waiting for the data to be ready
2. Copying the data from the kernel to the process
接下來的討論,會根據這兩階段的操作進行描述。
I/O一共有5大模型:
1、阻塞I/O
應用進程產生一個system call ,如果內核沒有數據準備好,則會一直wait,處于阻塞,當內核數據準備好之后,將會把數據從內核再拷貝到應用進程,這一copy過程也處于阻塞狀態。
2、非阻塞I/O
之所以稱作為非阻塞I/O,就意味著當應用進程產生一個system call的時候,不管內核的數據是否準備好,都會立即返回。而后,再一次發起call,這是一個輪詢的過程。當內核數據準備好之后,便可以正常進行響應。這一過程是非阻塞的。而當數據從內核copy到應用進程的過程,仍然是阻塞,應為要保證數據完整與一致。
3、I/O復用
使用I/O復用,一個或多個 system call 阻塞于select 或是 poll,而不是阻塞與真正的調用。當內核有數據準備好的時候,會通知select或是poll,接下來,會發起真正的system call,也就是圖片中的recvfrom。之后,便會正常copy數據到應用進程。值得注意的是,I/O復用產生了兩次system call,一次select(poll),一次recvfrom。因此,如果進程只是處理單一描述字(descriptor)的話,使用I/O復用不但不會有好的效果,而且還會有額外的系統開銷,所以,I/O復用一般都用于處理多個描述字(descriptors)的情況下。
4、信號驅動I/O
我們可以使用信號驅動I/O,當有描述字準備好后,內核會產生信號來通知應用進程。信號驅動模型不同于上述三種,對于應用進程而言,它在等待接受數據過程中,處于被通知狀態。這一過程,相當于一個異步操作。但是,對于內核copy數據到應用進程這一過程,應用進程仍然處于阻塞的狀態。
5、異步I/O
信號驅動I/O模型中,在等待內核數據準備階段中,是一個異步的過程,而數據copy階段則是阻塞的,也就是同步的。但是對于異步I/O模型而言,這兩個階段都是異步的。也就說,當引用進程產生一個aio_read后,它會繼續執行其他操作,整個過程不會產生任何阻塞。
“We call aio_read (the POSIX asynchronous I/O functions begin with aio_ or lio_) and pass the kernel the descriptor, buffer pointer, buffer size (the same three arguments for read), file offset (similar to lseek), and how to notify us when the entire operation is complete.” ——來自《Unix網絡編程》第三卷
5個I/O模型的比較總結:
總結:
在本文中,主要介紹了什么是I/O復用,I/O復用的應用場景,已經5大I/O模型的介紹。 在下一篇博文中,會重點介紹Unix環境下select和poll的原理、實際應用以及代碼實現。
![]() |
不含病毒。www.avast.com |