3 回答

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超7個(gè)贊
正如我在對(duì)上一個(gè)問(wèn)題的相關(guān)回答中所回答的那樣,您需要實(shí)現(xiàn)一個(gè)事件循環(huán);顧名思義,它是循環(huán)的,因此您應(yīng)該在父進(jìn)程中進(jìn)行編碼:
while (1) { // simplistic event loop! int status=0; if (waitpid(pid, &status, WNOHANG) == pid) { // clean up, child process has ended handle_process_end(status); break; }; struct pollpfd pfd[2]; memset (&pfd, 0, sizeof(pfd)); // probably useless but dont harm pfd[0].fd = rpipe[0]; pfd[0].events = POLL_IN; pfd[1].fd = wpipe[1]; pfd[0].event = POLL_OUT; #define DELAY 5000 /* 5 seconds */ if (poll(pfd, 2, DELAY)>0) { if (pfd[0].revents & POLL_IN) { /* read something from rpipe[0]; detect end of file; you probably need to do some buffering, because you may e.g. read some partial line chunk written by the child, and you could only handle full lines. */ }; if (pfd[1].revents & POLL_OUT) { /* write something on wpipe[1] */ }; } fflush(NULL);} /* end while(1) */
您無(wú)法預(yù)測(cè)管道的可讀或可寫(xiě)順序,并且這種情況可能會(huì)發(fā)生很多次。當(dāng)然,涉及很多緩沖(在父進(jìn)程中),我將詳細(xì)信息留給您。...您對(duì)子進(jìn)程中的緩沖沒(méi)有影響(某些程序檢測(cè)到它們的輸出是否為isatty)。
上面類似的事件輪詢循環(huán)為您避免死鎖情況,因?yàn)樽舆M(jìn)程的stdout管道已滿,子進(jìn)程被阻塞,而父進(jìn)程由于管道已滿而被阻止寫(xiě)入(寫(xiě)入子stdin管道)父進(jìn)程:循環(huán)時(shí),只要輪詢某些數(shù)據(jù)在輸入管道上即可讀?。醋舆M(jìn)程的stdout),便會(huì)讀取數(shù)據(jù),并且一旦輪詢輸出管道可寫(xiě)(即未滿)就可以寫(xiě)入一些數(shù)據(jù)。您無(wú)法預(yù)先預(yù)測(cè)這些事件“孩子的輸出可被父母讀取”和“孩子的輸入可被父母寫(xiě)入”的順序。
我建議閱讀高級(jí)Linux編程,其中有幾章解釋了這些問(wèn)題!
順便說(shuō)一句,我的簡(jiǎn)單事件循環(huán)有點(diǎn)不對(duì):如果子進(jìn)程終止并且某些數(shù)據(jù)保留在其stdout管道中,則不會(huì)完成其讀取。您可以waitpid
在poll
另外,不要期望單個(gè)write
(來(lái)自子進(jìn)程)進(jìn)入管道會(huì)觸發(fā)read
父進(jìn)程中的一個(gè)。換句話說(shuō),沒(méi)有消息長(zhǎng)度的概念。但是,POSIX知道PIPE_MAX
...。請(qǐng)參閱其編寫(xiě)文檔。也許您的緩沖區(qū)傳遞到read
和write
應(yīng)該的PIPE_MAX
大小。
我重復(fù)一遍:您需要在事件循環(huán)內(nèi)調(diào)用,poll
并且很有可能poll
會(huì)被調(diào)用多次(因?yàn)檠h(huán)將重復(fù)多次!),并且將以不可預(yù)測(cè)(且不可重現(xiàn))的順序報(bào)告可讀或可寫(xiě)的管道末端!程序的第一次運(yùn)行可能報(bào)告“ rpipe[0]
可讀”,read
從中可以得到324個(gè)字節(jié),重復(fù)事件循環(huán),poll
說(shuō)“ wpipe[1]
可寫(xiě)”,可以write
向其重復(fù)10個(gè)字節(jié),然后重復(fù)事件循環(huán),poll
則表明“ rpipe[0]
可讀”,您read
從中讀取110個(gè)字節(jié),重復(fù)事件循環(huán),poll
再次告訴“ rpipe[0]
可讀”,您read
4096個(gè)字節(jié),等等,等等...在相同環(huán)境中第二次運(yùn)行同一程序?qū)a(chǎn)生不同的事件,例如:poll
說(shuō)“ wpipe[1]
可寫(xiě)”,您write
對(duì)它寫(xiě)了1000個(gè)字節(jié),重復(fù)循環(huán),poll
說(shuō)“ rpipe[0]
可讀”等...
注意:您的問(wèn)題不是子程序(“客戶端”)中的緩沖,我們認(rèn)為您無(wú)法更改。因此,重要的不是其中的緩沖數(shù)據(jù),而是真正的輸入和輸出(這是父進(jìn)程唯一可以觀察到的內(nèi)容;內(nèi)部子緩沖區(qū)與父進(jìn)程無(wú)關(guān)),即子程序能夠執(zhí)行的數(shù)據(jù)真正 讀?。?)和寫(xiě)入(2)。并且如果通過(guò)pipe(7),則此類數(shù)據(jù)將在父進(jìn)程中變?yōu)?a >poll(2)-(并且您的父進(jìn)程可以在或之后的更新字段中read
或write
其中的一部分)。順便說(shuō)一句,如果您確實(shí)編碼了孩子,別忘了打電話給POLL_IN
POLL_OUT
revents
poll
fflush
在里面合適的地方。

TA貢獻(xiàn)1839條經(jīng)驗(yàn) 獲得超15個(gè)贊
您的代碼中似乎有兩個(gè)問(wèn)題。默認(rèn)情況下,“ stdout”是緩沖的,因此服務(wù)器應(yīng)顯式刷新它:
printf("I received %s\n", buffer);fflush(stdout);
并且POLLOUT
在嘗試讀取時(shí)主程序不應(yīng)注冊(cè)(但您可能想要注冊(cè)POLLERR
):
pfds[0].fd = rpipe[0];pfds[0].events = POLLIN | POLLERR;
通過(guò)這些修改,您可以獲得預(yù)期的輸出:
$ ./main寫(xiě)入數(shù)據(jù)...讀取數(shù)據(jù)...孩子說(shuō):我打招呼了
通常,您還應(yīng)該檢查的返回值poll()
,并在必要時(shí)重復(fù)調(diào)用(例如,在系統(tǒng)調(diào)用中斷或超時(shí)的情況下)。

TA貢獻(xiàn)1796條經(jīng)驗(yàn) 獲得超4個(gè)贊
從您的問(wèn)題中我感覺(jué)到您擁有服務(wù)器代碼,因此可以對(duì)其進(jìn)行修改。即使使用“ cat”,如果您按照pfds[0].events = POLLIN | POLLERR
我的建議進(jìn)行設(shè)置,它似乎也可以工作。但是,如果外部程序?qū)ζ漭敵鲞M(jìn)行緩沖(因此不會(huì)寫(xiě)入stdout),那么我認(rèn)為您無(wú)法做任何事情。
- 3 回答
- 0 關(guān)注
- 608 瀏覽
添加回答
舉報(bào)