系統(tǒng)提供select函數(shù)來實現(xiàn)多路復用I/O模型,select系統(tǒng)調用是用來讓我們的程序監(jiān)視多個文件句柄的狀態(tài)變化的。程序會停在select這里等待,直到被監(jiān)視的文件句柄有一個或多個發(fā)生了狀態(tài)改變。
創(chuàng)新互聯(lián)IDC提供業(yè)務:服務器托管,成都服務器租用,服務器托管,重慶服務器租用等四川省內主機托管與主機租用業(yè)務;數(shù)據(jù)中心含:雙線機房,BGP機房,電信機房,移動機房,聯(lián)通機房。
select API:
1)nfds參數(shù)指定被監(jiān)聽的文件描述符的總數(shù)。它通常被設置為select監(jiān)聽的所有文件描述符中的最大值加1,因為文件描述符是從0開始計數(shù)的。
2)readfds、writefds和exceptfds參數(shù)都是輸入輸出型參數(shù),分別指向可讀、可寫和異常等事件對應的文件描述符集合。作為輸入型參數(shù),應用程序調用select參數(shù)時,通過這三個參數(shù)傳入自己感興趣的文件描述符。作為輸出型參數(shù),select調用返回時,內核將修改它們來通知應用程序哪些文件描述符已經就緒。
fd_set結構體僅包含一個整型數(shù)組,該數(shù)組的每個元素的每一位(bit)標記一個文件描述符。fd_set能容納的文件描述符數(shù)量由FD_SETSIZE指定,這就限制了select能同時處理的文件描述符的數(shù)量。 系統(tǒng)提供了一系列宏來訪問fd_set結構體中的位: |
3)timeout參數(shù)用來設置select函數(shù)的超時時間。它是一個timeval結構類型的指針,采用指針參數(shù)是將它設置為輸入輸出型參數(shù),內核將修改它以告訴應用程序select等待了多久。
select給我們提供了一個微秒級的定時方式。如果給timeout變量的tv_sec和tv_usec都傳0,則select將立即返回。如果給timeout傳遞NULL,則select將一直阻塞,直到某個文件描述符就緒。
select成功時返回就緒(可讀、可寫和異常)文件描述符的總數(shù)。
如果在超時時間內沒有任何文件描述符就緒,select將返回0。
select失敗時返回-1并設置errno。如果在select等待期間,程序接收到信號,則select立即返回-1并設置errno為EINTER。
理解select
select模型的關鍵在于理解fd_set,假如取fd_set為一字節(jié),fd_set中的每一bit可以對應一個文件描述符fd,則1字節(jié)長的fd_set最大可以對應8個fd。
(1)執(zhí)行
fd_set set; FD_ZERO(&set);
則set用位表示是0000 0000。
(2)若fd=5,執(zhí)行
FD_SET(fd, &set);
后set變?yōu)?0001 0000(第5位設置為1)。
(3)若再加入fd = 2,fd = 1則set變?yōu)?0001 0011。
(4)執(zhí)行
select(6, &set, NULL, NULL, NULL);
阻塞等待。
(5)若fd = 1, fd = 2上都發(fā)生可讀事件,則select返回,此時set變?yōu)?000 0011。
注意:沒有事件發(fā)生的fd = 5被清空。
select模型的特點:
(1)可監(jiān)控的文件描述符個數(shù)取決于sizeof(fd_set)的值,一般為512或1024。假如服務器上sizeof(fd_set)的值為512,每個bit表示一個文件描述符,則服務器上支持的最大文件描述符是512 * 8 = 4096。如果想要調整fd_set的大小,可以通過編譯內核或其他方法。
(2)將fd加入select監(jiān)控的同時,還要再使用一個數(shù)組Array保存放到select監(jiān)控集中的fd,一是用于在select返回后,Array作為原數(shù)據(jù)和fd_set進行FD_ISSET判斷。二是select返回后會把以前加入的但并無事件發(fā)生的fd清空,所以每次開始select前都要重新從Array取得fd逐一加入(FD_ZERO最先),掃描Array的同時取得fd的最大值max_fd,用于select的第一個參數(shù)。
(3)select模型必須在select前遍歷Array(加fd,取max_fd),select返回后遍歷Array(FD_ISSET判斷是否有事件發(fā)生)。
select的優(yōu)點:
select的性能遠遠高于多進程、多線程。
select的缺點:
(1)select監(jiān)視的文件描述符數(shù)量是有限的
(2)每次調用select,都需要把fd集合從用戶態(tài)拷貝到內核態(tài),這個開銷在fd很多時會很大,導致服務器性能下降。
(3)每次調用都要在內核遍歷傳遞進來的所有fd,這個開銷在fd很多時也很大。
使用select 的TCP服務器