前面我們所有的**都是通過read和write操作, 每次只能處理乙個io請求. 但是io復用可以在同時處理多個socket的io請求. 而且io復用與執行緒連用是最常見的搭配.
本節介紹io多路復用select
函式.
#include
#include
#include
intselect
(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
struct timeval *timeout)
;
成功 : 返回事件發生的個數, 並且將返回改變的檔案符儲存在對應的集合中.
失敗 : 返回負數. 如果被中斷不可重啟, 會設定errno的值為eintr.
超時 : 返回0.
函式引數有點多, 可能一時間掌握不了可以慢慢做實驗體驗每個引數的意義.
select
函式有乙個叫檔案描述符集合的資料型別fd_set,fd_set
很像訊號集sigset_t而且兩者的實現都很相似.sigset_t
訊號集有32位之多, 每一位表示乙個訊號. 同樣fd_set
描述符集預設有1024位(最大值用fd_setsize表示), 每一位表示乙個檔案描述符.
sigset_t有一系列sigset
函式,fd_set
也同樣有一系列的操作函式 :
// 從描述符集中刪除fd
fd_clr
(int fd, fd_set *fdset)
;// 清除描述符集所有設定的描述符
fd_zero
(fd_set *fdset)
;// 將fd新增到描述符集中
fd_set
(int fd, fd_set *fdset)
;// 驗證fd是否在描述符集中
fd_isset
(int fd, fd_set *fdset)
;
我們使用本節介紹的select
函式來修改之前的**, 實驗驗證與write函式的不同.
將客戶端的**做了修改, 這裡只將修改的**貼出分析. 完整的** select_client.c
// 客戶端
intclient
(int port,
const
char
*cli_addr)
// 4if(
fd_isset
(sockfd,
&testrfds))}
close
(sockfd)
;return0;
}
需要注意幾點
將新的描述符集zero再新增檔案描述符
因為select返回會重置所有的描述符集, 所以必須將原描述符集儲存下來, 並且每次迴圈都要重新設定
需要對每乙個操作的描述符進行判斷
最終執行的結果可以看出正常的回射任何問題, 並且服務端關閉後客戶端立馬也就關閉了.
i/o多路復用技術(multiplexing)是什麼?
I O多路復用之select
阻塞i o模型 應用程式呼叫乙個i o函式,應用程式會一直等待資料準備好。如果資料沒有準備好,就會一直等待。只有當資料準備好,從核心拷貝到使用者空間io函式才成功返回。非阻塞i o模型 把乙個套介面設定成非阻塞告訴核心,當所有的i o操作無法完成時,不要將程序睡眠,而返回乙個錯誤資訊。此時i o操作...
IO多路復用之select
1 背景知識 我們首先來看看伺服器程式設計的模型,客戶端發來的請求服務端會產生乙個程序來對其進行服務,每當來乙個客戶請求就產生乙個程序來服務,然而程序不可能無限制的產生,因此為了解決大量客戶端訪問的問題,引入了io復用技術。即 乙個程序可以同時對多個客戶請求進行服務。也就是說io復用的 介質 是程序...
redis中io復用之select
前面講過evport epoll kqueue的實現,下來我們繼續看看我們select在redis中的使用 1 首先通過fd zero來清空用於監控讀和寫fd的rfds和wfds的鍊錶 typedef struct aeapistate aeapistate static int aeapicrea...