徹底學會使用epoll(四)——ET的寫操作例項分析
首先,看程式四的例子。
l 程式四
點選(此處)摺疊或開啟
-
#include <unistd.h>
-
#include <iostream>
-
#include <sys/epoll.h>
-
using namespace std;
-
int main(void)
-
{
-
int epfd,nfds;
-
struct epoll_event ev,events[5];//ev用於註冊事件,陣列用於返回要處理的事件
-
epfd=epoll_create(1);//只需要監聽一個描述符——標準輸出
-
ev.data.fd=STDOUT_FILENO;
-
ev.events=EPOLLOUT|EPOLLET;//監聽讀狀態同時設定ET模式
-
epoll_ctl(epfd,EPOLL_CTL_ADD,STDOUT_FILENO,&ev);//註冊epoll事件
-
for(;;)
-
{
-
nfds=epoll_wait(epfd,events,5,-1);
-
for(int i=0;i<nfds;i++)
-
{
-
if(events[i].data.fd==STDOUT_FILENO)
-
cout<<"hello world!"<<endl;
-
}
-
}
- };
這個程式的功能是隻要標準輸出寫就緒,就輸出“hello world!”。
執行結果:
我們發現這將是一個死迴圈。下面具體分析一下這個程式的執行過程:
(1) 首先初始buffer為空,buffer中有空間可寫,這時無論是ET還是LT都會將對應的epitem加入rdlist(對應第一節圖中的紅線),導致epoll_wait就返回寫就緒。
(2) 程式想標準輸出輸出”hello world!”和換行符,因為標準輸出為控制檯的時候緩衝是“行緩衝”,所以換行符導致buffer中的內容清空,這就對應第二節中ET模式下寫就緒的第二種情況——當有舊資料被髮送走時,即buffer中待寫的內容變少得時候會觸發fd狀態的改變。所以下次epoll_wait會返回寫就緒。之後重複這個過程一直迴圈下去。
我們再看程式五。
l 程式五
相對程式四這裡僅僅去掉了輸出的換行操作。即:
cout<<"hello world!";
執行結果如下:
我們看到程式成掛起狀態。因為第一次epoll_wait返回寫就緒後,程式向標準輸出的buffer中寫入“hello world!”,但是因為沒有輸出換行,所以buffer中的內容一直存在,下次epoll_wait的時候,雖然有寫空間但是ET模式下不再返回寫就緒。回憶第一節關於ET的實現,這種情況原因就是第一次buffer為空,導致epitem加入rdlist,返回一次就緒後移除此epitem,之後雖然buffer仍然可寫,但是由於對應epitem已經不再rdlist中,就不會對其就緒fd的events的在檢測了。
l 程式六
點選(此處)摺疊或開啟
-
int main(void)
-
{
-
int epfd,nfds;
-
struct epoll_event ev,events[5];//ev用於註冊事件,陣列用於返回要處理的事件
-
epfd=epoll_create(1);//只需要監聽一個描述符——標準輸出
-
ev.data.fd=STDOUT_FILENO;
-
ev.events=EPOLLOUT;//使用預設LT模式
-
epoll_ctl(epfd,EPOLL_CTL_ADD,STDOUT_FILENO,&ev);//註冊epoll事件
-
for(;;)
-
{
-
nfds=epoll_wait(epfd,events,5,-1);
-
for(int i=0;i<nfds;i++)
-
{
-
if(events[i].data.fd==STDOUT_FILENO)
-
cout<<"hello world!";
-
}
-
}
- };
程式六相對程式五僅僅是修改ET模式為預設的LT模式,我們發現程式再次死迴圈。這時候原因已經很清楚了,因為當向buffer寫入”hello world!”後,雖然buffer沒有輸出清空,但是LT模式下只有buffer有寫空間就返回寫就緒,所以會一直輸出”hello world!”,當buffer滿的時候,buffer會自動刷清輸出,同樣會造成epoll_wait返回寫就緒。
l 程式七
點選(此處)摺疊或開啟
-
int main(void)
-
{
-
int epfd,nfds;
-
struct epoll_event ev,events[5];//ev用於註冊事件,陣列用於返回要處理的事件
-
epfd=epoll_create(1);//只需要監聽一個描述符——標準輸出
-
ev.data.fd=STDOUT_FILENO;
-
ev.events=EPOLLOUT|EPOLLET;//監聽讀狀態同時設定ET模式
-
epoll_ctl(epfd,EPOLL_CTL_ADD,STDOUT_FILENO,&ev);//註冊epoll事件
-
for(;;)
-
{
-
nfds=epoll_wait(epfd,events,5,-1);
-
for(int i=0;i<nfds;i++)
-
{
-
if(events[i].data.fd==STDOUT_FILENO)
-
cout<<"hello world!";
-
ev.data.fd=STDOUT_FILENO;
-
ev.events=EPOLLOUT|EPOLLET;
-
epoll_ctl(epfd,EPOLL_CTL_MOD,STDOUT_FILENO,&ev); //重新MOD事件(ADD無效)
-
}
-
}
- };
程式七相對於程式五在每次向標準輸出的buffer輸出”hello world!”後,重新MOD OUT事件。所以相當於每次重新進行第一節中紅線描述的途徑返回就緒,導致程式迴圈輸出。
相關文章
- 徹底學會使用epoll(三)——ET的讀操作例項分析
- 徹底學會使用epoll(一)——ET模式實現分析模式
- 徹底學會使用epoll(五)—— ET模式下的注意事項模式
- 徹底學會使用epoll(六)——關於ET的若干問題總結
- 「linux」例項淺析epoll的LT和ET模式,ET模式為何要使用非阻塞IOLinux模式
- Epoll在LT和ET模式下的讀寫方式模式
- 【前端】一文徹底學會Promise前端Promise
- 徹底理解連結器:四
- 深入JavaScript系列(四):徹底搞懂thisJavaScript
- 30 個例項詳解 ,讓運維徹底搞清TOP 命令!運維
- 徹底學會 Go 指標 -- 就要學習 Go 語言Go指標
- ORACLE快速徹底Kill掉的會話Oracle會話
- 一文徹底熟練掌握並使用Java的NIO操作Java
- 徹底與加班說再見,藉助飛項學會任務管理,你也可以!
- JavaScript之例題中徹底理解thisJavaScript
- 用鬥地主的例項學會使用java Collections工具類Java
- 一文徹底弄懂Java的IO操作Java
- JVM指令分析例項四(陣列、switch)JVM陣列
- 「從原始碼中學習」徹底理解Vue選項Props原始碼Vue
- SAP徹底刪除物料主檔操作
- slub機制徹底圖解分析圖解
- 驗證.N“.NET研究”ET強命稱的思路和例項
- win10徹底禁用svchost如何操作 win10怎麼徹底關掉svchostWin10
- SAP 徹底刪除物料主資料操作
- 徹徹底底教會你使用Redux-saga(包含樣例程式碼)Redux
- 【日誌技術專題】「logback入門到精通」徹徹底底帶你學會logback框架的使用和原理(入門介紹篇)框架
- 【轉】JAVA IO 設計模式徹底分析Java設計模式
- 長尾理論的數學分析:真的徹底顛覆了二八法則?
- SWOT Analysis 四點(優勢、劣勢、機會、威脅)分析: 附可口可樂SWOT分析例項
- 如何使用CleanMyMac徹底擦除檔案?Mac
- 萬字長文帶你徹底學會攔截器與過濾器過濾器
- 徹底學會element-ui按需引入和純淨主題定製UI
- golang 字串操作例項Golang字串
- expdp/impdp操作例項
- for迴圈的例項分析
- 例項教程:1小時學會PythonPython
- YACC 例項分析
- 寫Java程式最容易犯的21種錯誤例項分析Java