2010-09-17 65 views
0

我正在創建一個子父母fork(),以便能夠通過管道與父母通信(/bin/sh)。execv,請選擇並閱讀

問題是: 在父級中,我在子輸出上設置了select(),但只在進程完成時才解除阻塞!所以當我跑步說ps沒關係。但是當我運行/bin/sh它不會輸出,直到shell退出。但我想讀它的輸出!

for(;;) { 
select(PARENT_READ+1,&sh,NULL,NULL,NULL); // This unblocks only when shell exits! 
if (FD_ISSET(PARENT_READ,&sh)) { 
    while (n = read (PARENT_READ, &buf,30)) { 
     buf[30]='\0'; 
     printf("C: %s\n",buf); 
    }; 
}; 
} 

答案是在禁用緩衝管道領域的某個地方?

+0

你有什麼參數exec()' - 殼?你怎麼提供一個管道?這些'pipe()'管道還是別的東西? – llasram 2010-09-17 12:07:31

+0

文件描述符沒有緩衝。 '/ bin/sh'可能只是在等待你的輸入 - 在發回任何東西之前。 – Dummy00001 2010-09-17 12:08:46

+0

1)我做了/ bin/sh的execv/execve 2)pipe()是一個管道,是的。 – JAmes 2010-09-17 12:09:40

回答

4

很多程序根據他們是否認爲他們正在與終端(tty)通話來改變他們的行爲,並且shell肯定會這樣做。此外,如果stdout是tty,則默認C流stdoutstderr可能無緩衝,否則將進行完全緩衝 - 這意味着直到內部緩衝區已滿,程序明確刷新它們或程序結束時纔會刷新它們。

要解決此問題,您必須讓您的程序假裝爲終端。爲此,您可以使用系統的僞終端API(嘗試man 7 pty)。最終結果是一對文件描述符,它們像管道一樣工作。另外,順便說一句,當選擇開鎖時,您應該從觸發的文件描述符中只讀一次。如果您多次閱讀,您可以使用循環讀取,但在後續讀取時可能會再次發生阻塞,除非您的FD處於非阻塞模式。

但是,我必須問:爲什麼你需要以這種方式與shell進行交互?可以說,只是運行一個shell腳本,或者使用「/ bin/sh -c your_command_here」而不是?實際上需要真正的終端正常工作的程序相對較少 - 主要是提示輸入密碼的程序,如ssh,susudo

+0

1)我試圖用大文件填滿緩衝區,但沒有任何反應! 2)我正在開發一個類似rsh的遠程shell,雖然有一個特殊的硬件,但是我不能使用套接字(它是一個複雜的情況,我知道)。 3)不要擔心循環 - 我需要閱讀至少一些東西! – JAmes 2010-09-17 12:17:32

+0

好的,如果你正在做類似rsh的事情,那麼你應該使用僞終端方法 - 這就是rsh和ssh在內部工作的方式。 – Doug 2010-09-17 12:19:28