轉載:http://blog.csdn.net/kkxgx/article/details/7717125
Linux上可以使用不同的I/O模型,我們可以通過下圖了解常用的I/O模型:同步和異步模型,以及阻塞和非阻塞模型,本文主要分析其中的異步阻塞模型。
一、select使用
這個模型中配置的是非阻塞I/O,然后使用阻塞select系統調用來確定一個I/O描述符何時有操作。使用select調用可以為多個描述符提供通知,對于每個提示符,我們可以請求描述符的可寫,可讀以及是否發生錯誤。異步阻塞I/O的系統流程如下圖所示:
使用select常用的幾個函數如下:
fd_set類型可以簡單的理解為按bit位標記句柄的隊列。具體的置位、驗證可以使用FD_SET,FD_ISSET等宏實現。在select函數中,readfds、writefds和exceptfds同時作為輸入參數和輸出參數,如果readfds標記了一個位置,則,select將檢測到該標記位可讀。timeout為設置的超時時間。下面我們來看如何使用select:
上面是一個服務器代碼的關鍵部分,設置為異步的模式,然后接受到連接將其添加到連接池中。監聽描述符上使用select,接受客戶端的連接請求,在check_client函數中,遍歷連接池中的描述符,檢查是否有事件發生。
二、poll使用
poll函數類似于select,但是其調用形式不同。poll不是為每個條件構造一個描述符集,而是構造一個pollfd結構體數組,每個數組元素指定一個描述符標號及其所關心的條件。定義如下:
每個結構體的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數據結構介紹:
常見的事件如下:EPOLLIN:表示對描述符的可以讀
EPOLLOUT:表示對描述符的可以寫
EPOLLPRI:表示對描述符的有緊急數據可以讀
EPOLLERR:發生錯誤
EPOLLHUP:掛起
EPOLLET:邊緣觸發
EPOLLONESHOT:一次性使用,當監聽完這次事件之后,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里
2)函數介紹
epoll的三個函數
功能:該函數生成一個epoll專用的文件描述符參數:size為epoll上能關注的最大描述符數
功能:用于控制某個epoll文件描述符時間,可以注冊、修改、刪除參數:epfd由epoll_create生成的epoll專用描述符
? ? op操作:EPOLL_CTL_ADD 注冊 ? EPOLL_CTL_MOD修改 ?EPOLL_DEL刪除
? ? ? ? ? ? fd:關聯的文件描述符
? ? evnet告訴內核要監聽什么事件
功能:該函數等待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/