2012-09-19 105 views
2

環境:在與海灣合作委員會x86_64的 2.6.32的Linux(RHEL 6.3)4.4.6新管道()和調用fork()C++ -

背景:我正在做一些繁重的數據搗鼓:約500 GB輸入數據分佈在〜2000個文件中。我的主要過程分叉N個孩子,每個孩子都會收到一份要緊縮的文件名列表。

我想要是用於控制檯I/O通過父母。我一直在尋找到pipe(),看看如何使用poll(),直到有錯誤消息讀給有我的父母塊一些有趣的東西。看起來我需要N管(每個孩子一個)並且通過我想聽的信號通過poll()。另外,我覺得,一旦我dup2(pipe[1], STDOUT)在每個孩子,每個孩子應該能寫到管道與cout << stuff;像往常一樣,對不對?

第一個,就是我上面說的關於多個管道,poll() ing和dup2()正確嗎?

第二個,我該如何設置父poll()循環,讓我一旦所有的孩子都死了,我就繼續前進?

眼下,這個代碼(不完整)的部分內容如下:

int status; 
while (1) { // wait for stuff 
    while ((status = poll(pollfds, ss.max_forks, -1)) > 1) 
     cout << "fork "<< status << ": " << pipes[status][0]; 
    if (status == -1) Die(errno, "poll error"); 
    if (status == 0) { // check that we still have at least one open fd 
     bool still_running = false; 
     for (int i=0; i<ss.max_forks; i++) { 
      // check pipe i and set still_running if it is not zero 
     } 
     if (!still_running) 
      break; 
    } 
} 

,我應該怎麼設置我的時候應該的fcntl設置()?我想做O_ASYNC嗎?我想做阻擋或非阻擋嗎?

+0

你期望有多少個孩子?也許你最好使用單一的fifo或域套接字。 –

回答

2

其實,你需要關閉()在這兩個進程(父母和子女)各自的「未使用」的一面,以確保「斷管」遇到。因此,如果子進程寫入Pipe [0],則父進程將從Pipe [1]中讀取並關閉自己的Pipe [0]。同樣,小孩會關閉Pipe [1]。

如果你這樣做,當它從管道讀的孩子已經死亡後,家長會得到一個錯誤。不要忘記使用一個waitpid()風格的函數來清理死亡進程。

您可能希望把手SETT爲非阻塞,所以你可以讀任何有無需使用1字節讀取這是很沒效率。雖然我只是用適當的緩衝區大小(通常爲1024或4096)進行一次read()調用,但如果有更多的數據,就讓下一個輪詢觸發。但是,我通常只有一個孩子可以工作,而不是幾百個:-)

至於你的循環,你必須跟蹤每個孩子的狀態,並退出時,你還沒有活着的孩子。

編輯:實際上,我發現我假設孩子是死的,當我得到即使POLLIN設置,或者讀一個0字節,當我得到POLLERR或POLLHUP標誌。不知道這種情況下是正確的......

+0

'read(2)'函數將返回0.它不完全是錯誤條件,它是file_的_end。 – fork0

+0

是的,我正在考慮補充說,作爲一種「感覺」,因爲這就是我正在尋找類似的設置使用select()。除了select()沒有「HUP」,這也是一個強大的候選人:-) –

1

這裏有一個問題,關於select() VS poll()What are the differences between poll and select?

但是,你有沒有想過使用線程,而不是單獨的進程?您可以更好地控制與線程的交互,通信通過數據結構而不是流水線I/O流。管道是昂貴的;你正在經歷操作系統,你必須格式化輸出的結果/解析輸入的結果,也很昂貴。最後一點:無論您是使用輕量級線程還是重量級的fork/exec,除非擁有2000個CPU多處理器,否則不需要一次啓動2000個。如果您爭用CPU的線程/進程比擁有CPU的線程/進程更多,您將創建一個非常昂貴且持續的上下文交換的情況。