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