Linux中有三種常見的I/O多路復用技術select、poll和epoll.它們的的出現是為了解決程序在進行大量I/O操作(如網絡通信)時的阻塞問題,使得用戶程序在I/O可用時得到通知,而不必一直阻塞等待每一個I/O操作。
I/O多路復用這個概念被提出來以后, select是第一個實現 (1983 左右在BSD里面實現)。其函數原型如下:
該函數第一個參數表明我們要監聽的文件描述符的最大值,中間的三個參數?readfds, writefds, exceptfds,指向描述符集,最后一個參數是超時時間。
select處理流程如圖所示:
但是,select模型有着一個很大的問題,那就是它所支持的fd的數量是有限制的,從linux源碼中所看
它所需要的fd_set類型其實是一個__FD_SETSIZE長度bit的數組。也就是說通過FD_SET宏來對它進行操作的時候,需要注意socket不能過大,否則可能出現數組寫越界的錯誤。
而linux在2.6 內核中引入的epoll模型,就徹底解決了這個問題。
epoll模型提供了三個接口:
其使用流程基本與select一致,大致如下:
epoll_create函數會為要監聽的fd分配內存。
epoll_ctl函數將要監聽的fd拷貝到內核空間,從而避免每次等待事件都要進行內存拷貝。同時,注冊一個回調函數到 fd的設備等待隊列中,這樣,當設備就緒的時候,驅動程序可以直接調用回調函數進行處理,從而避免了對所有監聽fd的輪循。
epoll_wait函數會檢查是否已經有fd就緒了,如果有則直接返回,如果沒有,則進入休眠狀態,直到被上述的回調函數喚醒或者超時時間到達。
關於select和epoll的源碼深層次分析,可以參考以下文章
http://blog.csdn.net/lizhiguo0532/article/details/6568964
http://hongxiaolong.com/posts/epoll.html