epoll和select區別
一篇好文,介紹epoll和select很清楚(問題引入,聯絡,區別以及用法)。後面它給的兩個連結,也很好。
-------------------------------
先說下本文框架,先是問題引出,然後概括兩個機制的區別和聯絡,最後介紹每個介面的用法
一、問題引出 聯絡區別
問題的引出,當需要讀兩個以上的I/O的時候,如果使用阻塞式的I/O,那麼可能長時間的阻塞在一個描述符上面,另外的描述符雖然有資料但是不能讀出來,這樣實時性不能滿足要求,大概的解決方案有以下幾種:
1.使用多程序或者多執行緒,但是這種方法會造成程式的複雜,而且對與程序與執行緒的建立維護也需要很多的開銷。(Apache伺服器是用的子程序的方式,優點可以隔離使用者)
2.用一個程序,但是使用非阻塞的I/O讀取資料,當一個I/O不可讀的時候立刻返回,檢查下一個是否可讀,這種形式的迴圈為輪詢(polling),這種方法比較浪費CPU時間,因為大多數時間是不可讀,但是仍花費時間不斷反覆執行read系統呼叫。
3.非同步I/O(asynchronous I/O),當一個描述符準備好的時候用一個訊號告訴程序,但是由於訊號個數有限,多個描述符時不適用。
4.一種較好的方式為I/O多路轉接(I/O multiplexing)(貌似也翻譯多路複用),先構造一張有關描述符的列表(epoll中為佇列),然後呼叫一個函式,直到這些描述符中的一個準備好時才返回,返回時告訴程序哪些I/O就緒。select和epoll這兩個機制都是多路I/O機制的解決方案,select為POSIX標準中的,而epoll為Linux所特有的。
區別(epoll相對select優點)主要有三:
1.select的控制代碼數目受限,在linux/posix_types.h標頭檔案有這樣的宣告:#define __FD_SETSIZE 1024 表示select最多同時監聽1024個fd。而epoll沒有,它的限制是最大的開啟檔案控制代碼數目。
2.epoll的最大好處是不會隨著FD的數目增長而降低效率,在selec中採用輪詢處理,其中的資料結構類似一個數組的資料結構,而epoll是維護一個佇列,直接看佇列是不是空就可以了。epoll只會對"活躍"的socket進行操作---這是因為在核心實現中epoll是根據每個fd上面的callback函式實現的。那麼,只有"活躍"的socket才會主動的去呼叫 callback函式(把這個控制代碼加入佇列),其他idle狀態控制代碼則不會,在這點上,epoll實現了一個"偽"AIO。但是如果絕大部分的I/O都是“活躍的”,每個I/O埠使用率很高的話,epoll效率不一定比select高(可能是要維護佇列複雜)。
3.使用mmap加速核心與使用者空間的訊息傳遞。無論是select,poll還是epoll都需要核心把FD訊息通知給使用者空間,如何避免不必要的記憶體拷貝就很重要,在這點上,epoll是通過核心於使用者空間mmap同一塊記憶體實現的。
二、介面
1)select
1. int select(int maxfdp1, fd_set *restrict readfds, fd_set *restrict writefds, fd_set *restrict exceptfds, struct timeval *restrict tvptr);
struct timeval{
long tv_sec;
long tv_usec;
}
有三種情況:tvptr == NULL 永遠等待;tvptr->tv_sec == 0 && tvptr->tv_usec == 0 完全不等待;不等於0的時候為等待的時間。select的三個指標都可以為空,這時候select提供了一種比sleep更精確的定時器。注意select的第一個引數maxfdp1並不是描述符的個數,而是最大的描述符加1,一是起限制作用,防止出錯,二來可以給核心輪詢的時候提供一個上屆,提高效率。select返回-1表示出錯,0表示超時,返回正值是所有的已經準備好的描述符個數(同一個描述符如果讀和寫都準備好,對結果影響是+2)。
2.int FD_ISSET(int fd, fd_set *fdset); fd在描述符集合中非0,否則返回0
3.int FD_CLR(int fd, fd_set *fd_set); int FD_SET(int fd, fd_set *fdset) ;int FD_ZERO(fd_set *fdset);
用一段linux 中man裡的話“FD_ZERO() clears a set.FD_SET() and FD_CLR() respectively add and remove a given file descriptor from a set. FD_ISSET() tests to see if a file descriptor is part of the set; this is useful after select() returns.”這幾個函式與描述符的0和1沒關係,只是新增刪除檢測描述符是否在set中。
2)epoll
1.int epoll_create(int size);
建立一個epoll的控制代碼,size用來告訴核心這個監聽的數目一共有多大。這個引數不同於select()中的第一個引數,給出最大監聽的fd+1的值。需要注意的是,當建立好epoll控制代碼後,它就是會佔用一個fd值,在linux下如果檢視/proc/程序id/fd/,是能夠看到這個fd的,所以在使用完epoll後,必須呼叫close()關閉,否則可能導致fd被耗盡。
2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件註冊函式,它不同與select()是在監聽事件時告訴核心要監聽什麼型別的事件,而是在這裡先註冊要監聽的事件型別。第一個引數是epoll_create()的返回值,第二個引數表示動作,用三個巨集來表示:
EPOLL_CTL_ADD:註冊新的fd到epfd中;
EPOLL_CTL_MOD:修改已經註冊的fd的監聽事件;
EPOLL_CTL_DEL:從epfd中刪除一個fd;
第三個引數是需要監聽的fd,第四個引數是告訴核心需要監聽什麼事,struct epoll_event結構如下:
struct epoll_event {
__uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
events可以是以下幾個巨集的集合:
EPOLLIN :表示對應的檔案描述符可以讀(包括對端SOCKET正常關閉);
EPOLLOUT:表示對應的檔案描述符可以寫;
EPOLLPRI:表示對應的檔案描述符有緊急的資料可讀(這裡應該表示有帶外資料到來);
EPOLLERR:表示對應的檔案描述符發生錯誤;
EPOLLHUP:表示對應的檔案描述符被結束通話;
EPOLLET: 將EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL佇列裡
關於epoll工作模式ET,LT
LT(level triggered)是預設的工作方式,並且同時支援block和no-block socket.在這種做法中,核心告訴你一個檔案描述符是否就緒了,然後你可以對這個就緒的fd進行IO操作。如果你不作任何操作,核心還是會繼續通知你的,所以,這種模式程式設計出錯誤可能性要小一點。傳統的select/poll都是這種模型的代表.
ET (edge-triggered)是高速工作方式,只支援no-block socket。在這種模式下,當描述符從未就緒變為就緒時,核心通過epoll告訴你。然後它會假設你知道檔案描述符已經就緒,並且不會再為那個檔案描述符傳送更多的就緒通知,直到你做了某些操作導致那個檔案描述符不再為就緒狀態了,但是請注意,如果一直不對這個fd作IO操作(從而導致它再次變成未就緒),核心不會發送更多的通知(only once)
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
等待事件的產生,類似於select()呼叫。引數events用來從核心得到事件的集合,maxevents告之核心這個events有多大,這個maxevents的值不能大於建立epoll_create()時的size,引數timeout是超時時間(毫秒,0會立即返回,-1永久阻塞)。該函式返回需要處理的事件數目,如返回0表示已超時。
三、參考:
APUE(I/O多路轉接)
linux man epoll select
相關推薦
epoll和select區別
一篇好文,介紹epoll和select很清楚(問題引入,聯絡,區別以及用法)。後面它給的兩個連結,也很好。 ------------------------------- 先說下本文框架,先是問題引出,然後概括兩個機制的區別和聯絡,最後介紹每個介面的用法 一、問題引
關於epoll和select的區別,哪些說法是正確的?----騰訊2016研發工程師線上模擬筆試題
關於epoll和select的區別,哪些說法是正確的? 正確答案: A B C epoll和select都是I/O多路複用的技術,都可以實現同時監聽多個I/O事件的狀態 epoll相比select效率更高,主要是基於其作業系統支援的I/O事件通知機
epoll為什麼快 及和select區別
epoll是多路複用IO(I/O Multiplexing)中的一種方式,但是僅用於linux2.6以上核心,在開始討論這個問題之前,先來解釋一下為什麼需要多路複用IO.以一個生活中的例子來解釋.假設你在大學中讀書,要等待一個朋友來訪,而這個朋友只知道你在A號樓,但是不知道
阿里開發者招聘節 | 面試題05: 關於epoll和select的區別,哪些說法是正確的?
為幫助開發者們提升面試技能、有機會入職阿里,雲棲社群特別製作了這個專輯——阿里巴巴資深技術專家們結合多年的工作、面試經驗總結提煉而
epoll和select
epoll和select 先說下本文框架,先是問題引出,然後概括兩個機制的區別和聯絡,最後介紹每個介面的用法 一、問題引出 聯絡區別 問題的引出,當需要讀兩個以上的I/O的時候,如果使用阻塞式的I/O,那麼可能長時間的阻塞在一個描述符上面,另外的描述符雖然有資料但是不能讀出來,這
非阻塞socket呼叫connect, epoll和select檢查連線情況示例
我們知道,linux下socket程式設計有常見的幾個系統呼叫: 對於伺服器來說, 有socket(), bind(),listen(), accept(),read(),write() 對於客戶端來說,有socket(),connect() 這裡主要要講的是客戶端
epoll和select效能比較
epoll是多路複用IO(I/O Multiplexing)中的一種方式,但是僅用於linux2.6以上核心,在開始討論這個問題之前,先來解釋一下為什麼需要多路複用IO.以一個生活中的例子來解釋.假設你在大學中讀書,要等待一個朋友來訪,而這個朋友只知道你在A號樓,但是不知道
關於TCP ,select,epoll伺服器的區別與聯絡
select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。而TCP伺服器要想實現多個描述符的等待需要用多程序多執
select、poll、epoll之間的區別
(1)select==>時間複雜度O(n) 它僅僅知道了,有I/O事件發生了,卻並不知道是哪那幾個流(可能有一個,多個,甚至全部),我們只能無差別輪詢所有流,找出能讀出資料,或者寫入資料的流,對他們進行操作。所以select具有O(n)的無差別輪詢複雜度,同時處理的流
select、poll、epoll之間的區別總結
select、poll、epoll都是IO多路複用的機制,先是監聽多個檔案描述符FD,一旦某個FD就緒,就可以進行相應的讀寫操作。但是select、poll、epoll本質都是同步I/O,他們都需要在讀寫事件就緒之後自己負責讀寫,即這個讀寫過程是阻塞的 1 se
為什麼epoll比select和poll更高效
執行epoll_create()函式會在核心建立一顆紅黑樹rb_node以及就緒連結串列rdllist(存放已經就緒的檔案描述符),監聽的檔案描述符數為系統可以開啟的最大檔案描述符數(65535)。接著使用者執行的epoll_ctl()函式將epoll_event結構體拷貝傳入核心,核心會在紅黑樹上新增相應的
Linux----網路程式設計(IO複用中select,poll,epoll之間的區別)
前面學習了select、poll和epoll三組IO複用系統呼叫,現在從向核心傳遞檔案描述符數、核心實現、檢索就緒描述符方式、工作模式和時間複雜度等五個方面比較其中的區別,以明確在實際應用中應該選擇使用哪個。 由於select與poll的特性相似,所以把它們聯絡在一起與ep
ORACLE中更新資料,PLSQL Developer中SELECT ... FOR UPDATE和 SELECT T.*,ROWID的區別
背景:ORACLE中更新少量資料時,在PLSQL Developer中,一般用的語句是SELECT FOR UPDATE和SELECT T.*,ROWID,這倆語句執行之後可以手動在查詢出來的資料中修改。例項背景:表名A,資料如下: ACOL1 COL2
Linq SelectMany和Select的區別
//IEnumerable<Book>.Select 將序列中的Authors元素投影到新表中. IEnumerable<List<Author>> EnumerableOfListOfAuthors = Bo
Select、poll、epoll之間的區別總結[整理]
select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒
SQL 中 SET 和 SELECT 有什麼區別???
SQL Server 中對已經定義的變數賦值的方式用兩種,分別是 SET 和 SELECT。對於這兩種方式的區別,SQL Server 聯機叢書中已經有詳細的說明,但很多時候我們並沒有注意,其實這兩種方式還是有很多差別的。 SQL Server推薦使用 SET 而不是 SEL
select poll epoll之間的區別比較
select,poll,epoll都是IO多路複用的機制。I/O多路複用就是通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事
insert into 和select into 插入記錄的區別
insert into table2(filed1,field2,...)select value1,value2,... from table1 可以從同一張表裡面讀取記錄,插入表中 select * into table2 from table1 從table1
Oracle:for update 和select t.*,t.rowid編輯資料的區別
1.select * from ls.lims_employees where empno='0001' for update只有當前使用者能檢視SELECT記錄,其他使用者可以select * fr
oracle中show user和select user from dual區別
出於好奇,去oracle中嘗試了一下這兩個語句。 1、首先執行show user——》 直接在sql視窗中執行發現,提示無效的