轉I O多路復用之select

2022-07-25 18:12:18 字數 2760 閱讀 4172

select的功能可以用一句話來描述:

實現基於i/o多路復用的非同步併發程式設計。

在具體講解select之前我們先看看常規的阻塞socket程式設計方式,以服務端為例:

對於這種方式,最大的問題在**呢?accept和recev的阻塞呼叫!下面以兩種場景為例,來說明相比這種情況,select是如何做到非同步i/o多路復用的高效性。

第一種場景server除了要對外響應client的服務外,還要能夠接受標準輸入的命令來進行管理。

假如使用上述阻塞方式,在單執行緒中,accept呼叫和read呼叫必定有先後順序,而它們都是阻塞的。比如先呼叫accept,後呼叫    read,那麼如果沒有客戶請求時,伺服器會一直阻塞在accept,沒有機會呼叫read,也就不能響應標準輸入的命令。    

1

intfd_stdin = open(...);

2

intfd_socket = socket(...);

3

bind(...);

4

listen(...);

5

while(1)

而如果使用select,先註冊分別由socket和open建立的檔案描述符,然後進入select呼叫。當其中任何乙個檔案描述符的狀態發生改變時,就可以進行相應的處理。

01

intfd_stdin = open(...);

02

intfd_socket = socket(...);

03

bind(...);

04

listen(...);

05

fd_set fs;

06

while(1)

第二種場景server要對外提供大量的client請求服務。

假如使用阻塞方式,在單執行緒中,由於accept和recev都是阻塞式的,那麼當乙個client被伺服器accept後,它可能在send傳送訊息時阻塞,因此伺服器就會阻塞在recev呼叫。即時此時有其他的client進行connect,也無法進行響應。

1

intfd_socket = socket(...);

2

bind(...);

3

listen(...);

4

while(1)

而如果使用select,在伺服器端先註冊由socket建立的檔案描述符,然後進入select呼叫。只有當由socket建立的檔案描述符的狀態發生改變時,才執行accept操作,並把得到的client的檔案描述符進行註冊,再次進入select呼叫。當select檢查到有檔案描述符的狀態改變時,如果是server的socket建立的檔案描述符,則執行accept操作,否則執行recev操作。當請求的client數目比較多時, select明顯能夠提高併發性。

01

intfd_socket = socket(...);

02

bind(...);

03

listen(...);

04

fd_set fs;

05

while(1)

14

15

if(fd_isset(fd_accept...))

16

recv(...);

17

}

說完了select相比阻塞呼叫的好處,我們也簡單說說它的限制和不足

(1)select在查詢狀態改變的檔案描述符時,是對描述符鍊錶進行遍歷操作,因此對效率有較大影響。

(2)select在預設情況下,支援的最大檔案描述符個數為1024。當然,可以通過修改linux的socket核心進行修改。

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...