select、poll、epoll使用小結

轉載:http://blog.csdn.net/kkxgx/article/details/7717125

Linux上可以使用不同的I/O模型,我們可以通過下圖了解常用的I/O模型:同步和異步模型,以及阻塞和非阻塞模型,本文主要分析其中的異步阻塞模型。


一、select使用

這個模型中配置的是非阻塞I/O,然后使用阻塞select系統調用來確定一個I/O描述符何時有操作。使用select調用可以為多個描述符提供通知,對于每個提示符,我們可以請求描述符的可寫,可讀以及是否發生錯誤。異步阻塞I/O的系統流程如下圖所示:


使用select常用的幾個函數如下:

[cpp]?view plaincopy
  1. FD_ZERO(int?fd,?fd_set*?fds)???
  2. FD_SET(int?fd,?fd_set*?fds)???
  3. FD_ISSET(int?fd,?fd_set*?fds)???
  4. FD_CLR(int?fd,?fd_set*?fds)???
  5. int?select(int?nfds,?fd_set?*readfds,?fd_set?*writefds,?fd_set?*exceptfds,?struct?timeval?*timeout)???
fd_set類型可以簡單的理解為按bit位標記句柄的隊列。具體的置位、驗證可以使用FD_SET,FD_ISSET等宏實現。在select函數中,readfds、writefds和exceptfds同時作為輸入參數和輸出參數,如果readfds標記了一個位置,則,select將檢測到該標記位可讀。timeout為設置的超時時間。

下面我們來看如何使用select:

[cpp]?view plaincopy
  1. SOCKADDR_IN?addrSrv;??
  2. int?reuse?=?1;??
  3. SOCKET?sockSrv,connsock;??
  4. SOCKADDR_IN?addrClient;??
  5. pool?pool;??
  6. int?len=sizeof(SOCKADDR);??
  7. /*創建TCP*/??
  8. sockSrv=socket(AF_INET,SOCK_STREAM,0);??
  9. /*地址、端口的綁定*/??
  10. ??
  11. addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);??
  12. addrSrv.sin_family=AF_INET;??
  13. addrSrv.sin_port=htons(port);??
  14. ??
  15. if(bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))<0)??
  16. {??
  17. ????fprintf(stderr,"Failed?to?bind");??
  18. ????return?;??
  19. }??
  20. ??
  21. if(listen(sockSrv,5)<0)??
  22. {??
  23. ????fprintf(stderr,"Failed?to?listen?socket");??
  24. ????return?;??
  25. }??
  26. setsockopt(sockSrv,SOL_SOCKET,SO_REUSEADDR,(const?char*)&reuse,sizeof(reuse));??
  27. init_pool(sockSrv,&pool);??
  28. while(1)??
  29. {??
  30. ????/*通過selete設置為異步模式*/??
  31. ????pool.ready_set=pool.read_set;??
  32. ????pool.nready=select(pool.maxfd+1,&pool.ready_set,NULL,NULL,NULL);??
  33. ????if(FD_ISSET(sockSrv,&pool.ready_set))??
  34. ????{??
  35. ????????connsock=accept(sockSrv,(SOCKADDR?*)&addrClient,&len);??
  36. ????????//loadDeal()/*連接處理*/??
  37. ????????//printf("test\n");??
  38. ????????add_client(connsock,&pool);//添加到連接池??
  39. ????}??
  40. ????/*檢查是否有事件發生*/??
  41. ????check_client(&pool);??
  42. }??
上面是一個服務器代碼的關鍵部分,設置為異步的模式,然后接受到連接將其添加到連接池中。監聽描述符上使用select,接受客戶端的連接請求,在check_client函數中,遍歷連接池中的描述符,檢查是否有事件發生。





二、poll使用

poll函數類似于select,但是其調用形式不同。poll不是為每個條件構造一個描述符集,而是構造一個pollfd結構體數組,每個數組元素指定一個描述符標號及其所關心的條件。定義如下:

[cpp]?view plaincopy
  1. #include?<sys/poll.h>??
  2. int?poll?(struct?pollfd?*fds,?unsigned?int?nfds,?int?timeout);??
  3. struct?pollfd?{??
  4. int?fd;?/*?file?descriptor?*/??
  5. short?events;?/*?requested?events?to?watch?*/??
  6. short?revents;?/*?returned?events?witnessed?*/??
  7. };??

每個結構體的events域是由用戶來設置,告訴內核我們關注的是什么,而revents域是返回時內核設置的,以說明對該描述符發生了什么事件。這點與select不同,select修改其參數以指示哪一個描述符準備好了。在《unix環境高級編程》中有一張events取值的表,如下:

POLLIN :可讀除高優級外的數據,不阻塞

POLLRDNORM:可讀普通數據,不阻塞

POLLRDBAND:可讀O優先數據,不阻塞

POLLPRI:可讀高優先數據,不阻塞

POLLOUT :可寫普數據,不阻塞

POLLWRNORM:與POLLOUT相同

POLLWRBAND:寫非0優先數據,不阻塞

其次revents還有下面取值

POLLERR :已出錯

POLLHUP:已掛起,當以描述符被掛起后,就不能再寫向該描述符,但是仍可以從該描述符讀取到數據。

POLLNVAL:此描述符并不引用一打開文件

對poll函數,nfds表示fds中的元素數,timeout為超時設置,單位為毫秒若為0,表示不等待,為-1表示描述符中一個已經準備好或捕捉到一個信號返回,大于0表示描述符準備好,或超時返回。函數返回值返回值若為0,表示沒有事件發生,-1表示錯誤,并設置errno,大于0表示有幾個描述符有事件。

poll的使用和select基本類似。在此不再介紹。poll相對于是select的優勢是監聽的描述符數量沒有限制。

三、epoll學習

epoll有兩種模式,Edge Triggered(簡稱ET) 和 Level Triggered(簡稱LT).在采用這兩種模式時要注意的是,如果采用ET模式,那么僅當狀態發生變化時才會通知,而采用LT模式類似于原來的select/poll操作,只要還有沒有處理的事件就會一直通知.

1)epoll數據結構介紹:

[cpp]?view plaincopy
  1. typedef?union?epoll_data??
  2. {??
  3. ??void????????*ptr;??
  4. ??int??????????fd;??
  5. ??__uint32_t???u32;??
  6. ??__uint64_t???u64;??
  7. }?epoll_data_t;??
  8. ??
  9. struct?epoll_event??
  10. {??
  11. ??__uint32_t???events;?/*?Epoll?events?*/??
  12. ??epoll_data_t?data;???/*?User?data?variable?*/??
  13. };??
常見的事件如下:

EPOLLIN:表示對描述符的可以讀

EPOLLOUT:表示對描述符的可以寫

EPOLLPRI:表示對描述符的有緊急數據可以讀

EPOLLERR:發生錯誤

EPOLLHUP:掛起

EPOLLET:邊緣觸發

EPOLLONESHOT:一次性使用,當監聽完這次事件之后,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里

2)函數介紹

epoll的三個函數

[cpp]?view plaincopy
  1. int?epoll_creae(int?size);??
功能:該函數生成一個epoll專用的文件描述符

參數:size為epoll上能關注的最大描述符數

[cpp]?view plaincopy
  1. int?epoll_ctl(int?epfd,?int?op,?int?fd,?struct?epoll_event?*event);??
功能:用于控制某個epoll文件描述符時間,可以注冊、修改、刪除

參數:epfd由epoll_create生成的epoll專用描述符

? ? op操作:EPOLL_CTL_ADD 注冊 ? EPOLL_CTL_MOD修改 ?EPOLL_DEL刪除

? ? ? ? ? ? fd:關聯的文件描述符

? ? evnet告訴內核要監聽什么事件

[cpp]?view plaincopy
  1. int?epoll_wait(int?epfd,struct?epoll_event*events,int?maxevents,int?timeout);??
功能:該函數等待i/o事件的發生。

參數:epfd要檢測的句柄

? ? ?events:用于回傳待處理時間的數組

? ? ?maxevents:告訴內核這個events有多大,不能超過之前的size

? ? ?timeout:為超時時間

使用方法參考:https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/epoll-example.c


epoll支持的FD上限是最大可以打開文件的數目(select面臨這樣的問題),IO效率不隨FD數目增加而線性下降(select、poll面臨的問題)使用mmap加速內核與用戶空間的消息傳遞。現在libevent封裝了幾種的實現,可以通過使用libevent來實現多路復用。


?本文參考:https://banu.com/blog/2/how-to-use-epoll-a-complete-example-in-c/

? ?http://www.ibm.com/developerworks/cn/linux/l-cn-edntwk/index.html?ca=drs-

? ? ? ? ? ? ?http://www.ibm.com/developerworks/cn/linux/l-async/


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/news/384432.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384432.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384432.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Qt報錯:undefined reference to xxxxx

報錯信息&#xff1a; 首先&#xff0c;要區分與undefined reference to xxxxx和 "xxxx was not declared in this scope"兩種報錯信息的差別&#xff0c;前者是因為編譯器能找到函數的聲明&#xff0c;但是找不到函數的定義&#xff0c;從而報錯&#xff1b;而后者是…

inet_pton, inet_ntop

轉自&#xff1a;http://www.cnblogs.com/s7vens/archive/2011/12/12/2284964.html Linux下這2個IP地址轉換函數&#xff0c;可以在將IP地址在“點分十進制”和“整數”之間轉換 而且&#xff0c;inet_pton和inet_ntop這2個函數能夠處理ipv4和ipv6。算是比較新的函數了。inet…

htonl(), ntohl(), htons(), ntohs() 函數

轉自&#xff1a;http://www.cnblogs.com/s7vens/archive/2011/12/12/2284892.html 在C/C寫網絡程序的時候&#xff0c;往往會遇到字節的網絡順序和主機順序的問題。這是就可能用到htons(), ntohl(), ntohs()&#xff0c;htons()這4個函數。 網絡字節順序與本地字節順序之間的…

inet_ntoa、 inet_aton、inet_addr

轉自&#xff1a;http://blog.csdn.net/zhangboyj/article/details/6157263 inet_addr() 簡述&#xff1a;將一個點間隔地址轉換成一個in_addr。 #include <winsock.h> unsigned long PASCAL FAR inet_addr( const struct FAR* cp); cp&#xff1a;一個以Internet標準“.…

對象的淺拷貝和深拷貝

對象的淺拷貝和深拷貝簡要介紹代碼實現簡要介紹 淺拷貝&#xff1a;python拷貝一般都是淺拷貝。拷貝時&#xff0c;對象包含的子對象內容不拷貝。因此&#xff0c;源對象和拷貝對象引用同一個對象 深拷貝&#xff1a;使用copy模塊的deepcopy函數&#xff0c;遞歸拷貝對象中包含…

用模板寫單鏈表

轉載自&#xff1a;http://blog.csdn.net/itcastcpp/article/details/39081953 為了加深對模板的理解&#xff0c;我們今天一起用模板寫一個單鏈表&#xff0c;希望通過這個例子&#xff0c;能夠幫助大家加深對模板的體會&#xff0c;具體如下&#xff1a; SList.hpp內容&#…

QT事件事件之一:Qt中的事件處理與傳遞

QT事件事件之一&#xff1a;Qt中的事件處理與傳遞前言一、簡介二、QT中的事件三、事件的實現的方法前言 在QT中&#xff0c;事件是我們很常用的東西&#xff0c;以下是我用事件時總結和做法 一、簡介 在QT中&#xff0c;事件作為一個對象&#xff0c;繼承QEvent類&#xff0c…

linux下成功安裝ffmpeg( 親測有效 )

linux下成功安裝ffmpeg&#xff08; 親測有效 &#xff09;一、下載二、安裝步驟1.安裝yasm2.安裝ffmpeg總結一、下載 ffmpeg 官網下載&#xff1a; http://ffmpeg.org/download.html 安裝yasm 官網下載&#xff1a;http://yasm.tortall.net/Download.html 二、安裝步驟 1.…

C++實現 簡單 單鏈表

轉自&#xff1a; http://blog.csdn.net/wonggonghong/article/details/21527577 我們首先建立一個<List.h>頭文件&#xff0c;聲明一個單鏈表結構&#xff1a; #include "List.h" [cpp] view plaincopy //創建一個單鏈表結構&#xff0c;包含一些常見的操作 …

ffmpeg音視頻基礎知識

ffmpeg音視頻基礎知識前言一、圖像的基礎知識二、視頻編碼基礎知識1.視頻和圖片之間的關系2.為什么要編碼&#xff1f;3.什么是編碼&#xff1f;視頻相關專業術語提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄前言…

數據結構之單鏈表——C++模板類實現

轉自&#xff1a;http://blog.csdn.net/Mrx_Nh/article/details/60471647 單鏈表定義 [cpp] view plaincopy #ifndef SinglyLinkedListEDLIST_H_INCLUDED #define SinglyLinkedListEDLIST_H_INCLUDED #include <bits/stdc.h> using namespace std; template&l…

Linux系統編程(一)

Linux系統編程&#xff08;一&#xff09;一、進程和程序二、內存布局內核空間用戶空間三、進程狀態四、環境變量五、進程共享一、進程和程序 程序&#xff1a;是指編譯好的二進制文件&#xff0c;存儲在磁盤中&#xff0c;不占用系統資源。 進程&#xff1a;是系統進行資源分…

Linux的SOCKET編程 簡單演示

轉載&#xff1a;http://blog.csdn.net/hguisu/article/details/7445768/ Linux的SOCKET編程詳解 1. 網絡中進程之間如何通信 進 程通信的概念最初來源于單機系統。由于每個進程都在自己的地址范圍內運行&#xff0c;為保證兩個相互通信的進 程之間既互不干擾又協調一致工作&a…

Unity(一)必然事件

【MonoBehaviour 類】&#xff08;一&#xff09;必然事件一、必然事件是什么&#xff1f;二、常用函數執行順序1.Awake2.Start3.update4.FixedUpdate三、Awake和start區別一、必然事件是什么&#xff1f; 在Unity中必然事件也稱腳本生命周期&#xff0c;是指在Unity腳本在喚醒…

正則匹配函數

轉載&#xff1a;http://blog.csdn.net/ithomer/article/details/6130806 1.int regcomp(regex_t *compiled, const char *pattern, int cflags) 這個函數把指定的規則表達式pattern編譯成一種特定的數據格式compiled&#xff0c;這樣可以使匹配更有效。函數regexec會使用這個數…

Linux系統編程(二)孤兒進程和僵尸進程

Linux系統編程&#xff08;二&#xff09;一、exec函數族1.exec函數二、孤兒進程和僵尸進程三、wait和waitpid1.wait函數2.waitpid函數一、exec函數族 exec函數使用時&#xff0c;改程序的用戶空間的代碼和數據會被新程序給替代&#xff0c;會從新程序的啟動例程開始。調用exe…

linux下c/c++實例之十socket簡單應用

轉自&#xff1a;http://blog.csdn.net/taiyang1987912/article/details/49738351 一、簡介 通過socket掃描本機打開的tcp端口號&#xff0c;模擬用戶名、密碼登錄服務器的過程、socket文件傳輸及模仿http服務器。 二、詳解 1、Linux下tcp端口掃描 &#xff08;1&#xff09;…

Linux系統編程(三)進程間的通信

Linux系統編程&#xff08;三&#xff09;進程間的通信一、為什么需要進程之間的通信&#xff08;IPC&#xff09;&#xff1f;二、管道1.概念2.特質3.原理4.局限性5.代碼2.讀入數據三、共享存儲映射注意事項父子進程通信一、為什么需要進程之間的通信&#xff08;IPC&#xff…

使用mmap實現大文件的復制:單進程與多進程情況

單線程和多進程實現文件的復制&#xff08;mmap方法&#xff09; mmap實現大文件的復制單線程和多進程實現文件的復制&#xff08;mmap方法&#xff09;一、單線程實現二、多進程實現一般文件實現方法&#xff1a;1.讀取&#xff08;fread&#xff09;要復制的文件2.寫入&#…

exec 函數族

轉自&#xff1a;http://www.cnblogs.com/mickole/p/3187409.html linux系統編程之進程&#xff08;五&#xff09;&#xff1a;exec系列函數&#xff08;execl,execlp,execle,execv,execvp)使用 本節目標&#xff1a; exec替換進程映像exec關聯函數組&#xff08;execl、execl…