[問題] 想請問一個epoll以及pipe的問題

看板C_and_CPP作者 (^^)時間10年前 (2015/07/28 19:11), 編輯推噓4(4026)
留言30則, 3人參與, 最新討論串1/1
開發平台(Platform): (Ex: VC++, GCC, Linux, ...) c++11 問題(Question): 當pipe在其他thread瞬間大量寫入時, epoll_wait只會被喚醒一次, 如果沒一次把data全部讀完就會卡在epoll_wait 除非改成epoll_wait(efd, events, MAXEVENTS, 1000); 預期的正確結果(Expected Output): 每輪只從各fd讀取一部份資料, 要如何得知還有data未讀取, 並在下一輪繼續讀取剩下的資料呢? 程式碼(Code):(請善用置底文網頁, 記得排版) 以下是簡化後示意的程式碼: http://codepad.org/8af9AZkm g++ -o main.o main.cpp --std=c++0x -lpthread 請問一般時如何實作這種不會一次讀完的情況呢? 或是當要read的資料(stream)超過buffer時, 要如何每次只讀取各stream的一部分呢? 麻煩各為可以替我解答, 謝謝 -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 220.129.49.238 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1438081908.A.1B3.html

07/28 22:06, , 1F
不確定需求. 你不能就一直讀讀到完?
07/28 22:06, 1F

07/28 23:03, , 2F
你需要有一個結構來紀錄每個 fd 上次讀了多少 byte
07/28 23:03, 2F

07/28 23:03, , 3F
等到該 fd 下次又可以讀取時,寫入時的 buffer 加上
07/28 23:03, 3F

07/28 23:03, , 4F
之前已經紀錄的 byte 數,當作是 offset 來寫入
07/28 23:03, 4F

07/28 23:05, , 5F
大多數的 non-blocking I/O multiplexing 都是這樣寫的
07/28 23:05, 5F

07/28 23:06, , 6F
目的就是每個 fd 都要被讀取一點,簡單點可以開一個
07/28 23:06, 6F

07/28 23:08, , 7F
array (e.g. size_t avaiLen[MAX_FDS]) 之類的作法
07/28 23:08, 7F

07/28 23:09, , 8F
把每次 read (or recv) 回傳的長度,針對fd作一個紀錄
07/28 23:09, 8F

07/28 23:10, , 9F
non-blocking I/O multiplexing 的重點就是要輪流讀取
07/28 23:10, 9F

07/28 23:11, , 10F
千萬不要寫 loop 硬是把資料給讀完,這樣就失去意義了
07/28 23:11, 10F

07/28 23:13, , 11F
另外,你得考慮你的通訊協定,或者實作一個自動狀態機
07/28 23:13, 11F

07/28 23:14, , 12F
進而得知當前讀取的 buf 已經可以進行 parse 之類的
07/28 23:14, 12F

07/28 23:15, , 13F
修正用語,是 FSM 有限狀態自動機。
07/28 23:15, 13F

07/28 23:16, , 14F
還有這篇文章可以看看,reactor pattern 就是你想要的
07/28 23:16, 14F

07/28 23:16, , 15F
http://goo.gl/ULuXrX Reactor (Douglas C. Schmidt)
07/28 23:16, 15F

07/28 23:19, , 16F
另外,每個 fd 都要有自己的 buffer,這樣才能夠多工
07/28 23:19, 16F

07/28 23:22, , 17F
建議可以直接用一個結構來儲存 buf 跟 avaiLen 之類的
07/28 23:22, 17F

07/28 23:23, , 18F
e.g. struct ctx { char buf[8192]; size_t len; };
07/28 23:23, 18F

07/29 13:37, , 19F
非常謝謝您們的回答^^
07/29 13:37, 19F

07/29 13:37, , 20F
嗯嗯我預計會有個connect物件來記錄這些
07/29 13:37, 20F

07/29 13:44, , 21F
用select就能達到我想要的~不過epoll就會卡住QQ
07/29 13:44, 21F

07/29 13:48, , 22F
http://codepad.org/LdltMzU4 這是改用select的程式碼
07/29 13:48, 22F

07/29 17:45, , 23F
再看一次你的程式,你得把EPOLLET改EPOLLLT,才會持續
07/29 17:45, 23F

07/29 17:46, , 24F
通知。不然就得寫迴圈把資料讀玩。這樣就有別一般的
07/29 17:46, 24F

07/29 17:48, , 25F
select()用法了。改看看再回報結果吧:)
07/29 17:48, 25F

07/29 21:30, , 26F
哇可以了耶~非常謝謝您
07/29 21:30, 26F

07/29 21:31, , 27F
ubutun 14.10 EPOLLLT已經是epoll預設模式
07/29 21:31, 27F

07/29 21:32, , 28F
拿掉EPOLLLT即可^^
07/29 21:32, 28F

07/29 21:34, , 29F
恭喜你,建議這篇文章也可以看看 http://goo.gl/3oBXMm
07/29 21:34, 29F

07/29 21:34, , 30F
進而理解 EPOLLET 與 EPOLLLT (預設) 的差異
07/29 21:34, 30F
文章代碼(AID): #1LjsDq6p (C_and_CPP)