i/o多路復用模型允許我們同時等待多個套接字描述符是否就緒。linux系統為實現i/o多路復用提供的最常見的乙個函式是select
函式,該函式允許程序指示核心等待多個事件中的任何乙個發生,並只有在乙個或多個事件發生或經歷一段指定的時間後才喚醒它。
作為乙個例子,我們可以呼叫select
,告知核心僅在下列情況發生時才返回:
也就是說,我們呼叫select
可以告知核心我們對哪些描述符感興趣以及等待多久時間。
select
是乙個複雜的函式,有許多不同的應用場景,我們將只討論第一種場景:等待一組描述符準備好讀。
#include
#include
int select(int n, fd_set *fdset, null, null, struct timeval *timeout);
fd_zero(fd_set *fdset); // 將fdset初始為為空集合
fd_clr(int fd, fd_set *fdset); // 從fdset清除fd
fd_set(int fd, fd_set *fdset); // 將fd新增到fdset
fd_isset(int fd, fd_set *fdset); // fd是否存在於fdset
我們來看下select
函式的引數。引數n
指定需要測試的描述符的數目,測試的描述符範圍從0到n-1。第二個引數fdset
指定需要測試的可讀描述符集合。當fdset
集合中有描述符可讀,或者經歷了timeout
時間時,select
將返回。當select
返回時,作為乙個***,select
修改了引數fdset
指向的描述符集合,這時fdset
變成由讀集合中準備好可以讀了的描述符組成。select
函式的返回值則指明了就緒集合的基數。值得注意的是,由於這個***,我們必須每次在呼叫select
時都更新讀集合。
#include
#include
#include
#include
#include
#include
#include
#include
int main()
for (fd = 0; fd < fd_setsize; fd++)
// 如果是舊的客戶活動
else
// 客戶請求資料到達
else }}
}}
}
上面的**展示了如何使用select
來編寫多併發伺服器的過程。伺服器可以讓select
呼叫同時檢查監聽套接字和已連線套接字。一旦select
指示有活動發生,就可以用fd_isset
來遍歷所有可能的檔案描述符,以檢查是哪個描述符上面有活動發生。
如果是監聽套接字可讀,這說明正有乙個客戶試圖建立連線,此時就可以呼叫accept
建立乙個客戶的已連線套接字而不用擔心阻塞。如果是某個客戶描述符準備好,這說明該描述符上有乙個客戶請求需要我們讀取處理。如果讀操作返回零位元組,這表示有乙個客戶程序已結束,這時我們可以關閉該套接字並把它從描述符集合中刪除。
深入理解計算機系統,第2版,機械工業出版社
linux程式設計(第4版),neil matthew等著,人民郵電出版社,2023年
unix 網路程式設計卷1:套接字聯網api(第三版), w.richard stevens 等著
I O多路復用之select
阻塞i o模型 應用程式呼叫乙個i o函式,應用程式會一直等待資料準備好。如果資料沒有準備好,就會一直等待。只有當資料準備好,從核心拷貝到使用者空間io函式才成功返回。非阻塞i o模型 把乙個套介面設定成非阻塞告訴核心,當所有的i o操作無法完成時,不要將程序睡眠,而返回乙個錯誤資訊。此時i o操作...
IO多路復用之select
1 背景知識 我們首先來看看伺服器程式設計的模型,客戶端發來的請求服務端會產生乙個程序來對其進行服務,每當來乙個客戶請求就產生乙個程序來服務,然而程序不可能無限制的產生,因此為了解決大量客戶端訪問的問題,引入了io復用技術。即 乙個程序可以同時對多個客戶請求進行服務。也就是說io復用的 介質 是程序...
I O多路復用之select
select是用於監視多個檔案描述符狀態的變化的。即用來監視檔案描述符讀 寫 異常狀態是否就緒。函式原型 int select int nfds,fd set readfds,fd set writefds,fd set exceptfds,struct timeval timeout select...