Linux的三種I O復用方式 select

2021-09-19 12:32:00 字數 1781 閱讀 9045

select

poll

epollselect的原型是

int select(int maxfd,fd_set *readfds,fd_set,fd_set *writefds,fd_set *exceptfds,struct timeval *timeout);
maxfd
:監聽的最大檔案描述符的值+1//輪詢每次要遍歷的位數,大於檔案描述符總數

readfds,writefds,exceptfds:分別記錄關注的可讀,可寫,異常三種事件的檔案描述符的集合

timeout:設定select一次監聽的時間,當沒有檔案描述符就緒,則超時,select返回0,null永久阻塞。

思考兩個問題:

如何將使用者關注的檔案描述符設定到fd_set結構體變數

select返回之後如何判斷哪些檔案描述符有事件

我們先來看看fd_set原型

struct

fd_set

fd_set使用按bit儲存訊息,32*32 = 1024位,也就是可以儲存1024個檔案描述符,為什麼能儲存1024個檔案識別符號?因為long int 是4位元組32位,每一位上初始值為0,當某乙個檔案描述符有改動,則那一位上置1,正好1024個,每次select返回有多少個檔案描述符有改動(也就是事件被觸發),無法得知那些被改動。如果select在等待期間收到訊號,則會立即返回-1,並設定error為eintr。

這裡使用了位運算,我們進行一些拓展:

fd_set(指標)/32就是獲得結構體中fds_bits的某一位位址+fd_set%32 = fds_bits響應檔案描述符的位置

也就是說陣列的某一位位址下標 | 1《因為位運算過於複雜,系統為我們提供了一些巨集,如下

**fd_zero(fd_set *fds);//初始化,清空

fd_set(int fd,fd_set *fds);將fd設定到fds上

fd_clr(int fd,fd_set fds);清除fds上的fd

fd_isset(int fd,fd_set fds);判斷fds上的fd檔案描述符是否有事件發生(有修改)

其中,fd_isset返回值為1表明有改動,0表示沒有改動

舉個例子

fd_set read;//宣告fd_set

fd_zero(&read);

int n = select(&read);

n == 1 fd_isset(3,&read) == 0;/判斷3這個fd有沒有被修改,返回0表示3這個檔案描述符沒有被修改

#include #include #include #include #include #include #include #include #include #include #define fdmax 100

int fdall[fdmax];

int maxfd = -1;

void init_fdall()

} int n = select(maxfd+1,&read,null,null,null);//返回已就緒的檔案描述符個數

if(n <= 0)

i = 0;

for(;i select的缺點:

只能關注三種事件型別

fd_set 最大1024位,也就是0-1023

返回值探測只返回就緒檔案個數,使用者探測就緒的檔案描述符的時間複雜度位o(n)

核心使用輪詢的方式檢測就緒檔案描述符,核心事件複雜度也是o(n)

Linux的三種I O復用方式 poll

select poll epollpoll的原型是 int poll struct pollfd fds,int nfds,int timeout struct pollfd ndfs 傳入的結構體陣列長度,因為此時的 fds會退化為指標,更準確的來說,ndfs的型別是ndfs t是無型別的long...

IO復用的三種模型

阻塞式i o 所有套接字預設 非阻塞i o i o復用 select,poll,epoll 訊號驅動式 sigio 核心在描述符就緒時傳送sigio通知程序 非同步i o posix的aio 系列函式 不會阻塞。核心完成後整個操作,通知程序。同步i o 真正的io操作程序會阻塞,直到i o程式結束 ...

三種I O多路復用機制學習記錄 select 2

現在開始學習三種i o多路復用機制的第二種 select,上篇文章也講到,由於我水過了作業系統的上機,因此要不停的補坑,在校的各位未來程式設計師們,上課要好好學習,一定要自己敲。select我真的有點不記得了,但是學過go語言的通道後,一定也會知道go語言中也有乙個select,這兩個select功...