0
我試圖編寫一個程序C
創建2個子進程,其中每個進程執行execvp
。管道問題:第一個孩子寫入太多
我的問題是,第一個孩子寫太多的輸入到另一個孩子讀的管道。
int main(int argc, char* argv[]){
//unnamed pipe
int pipeFd[2], statusFirst,statusSecond;
pid_t childPidOne,childPidTwo;
if(pipe(pipeFd) < 0){
perror("Pipe error:\n");
exit(EXIT_FAILURE);
}
switch(childPidOne = fork()){
case -1:
perror("First Fork error:\n");
exit(EXIT_FAILURE);
case 0:
printf("First child\n");
close(pipeFd[1]);
if((execvp(argv[1], &argv[1])) < 0){
perror("First execvp error:\n");
}
printf("End First cild\n");
exit(0);
default:
//Do nothing
break;
}
switch(childPidTwo = fork()){
case -1:
perror("Second Fork error:\n");
exit(EXIT_FAILURE);
case 0:
printf("Second cild\n");
close(pipeFd[0]);
if((execvp(argv[3], &argv[3])) < 0){
perror("Second execvp error:\n");
}
printf("End Second cild\n");
exit(0);
default:
//Do nothing
break;
}
close(pipeFd[0]);
close(pipeFd[1]);
if((waitpid(childPidOne,&statusFirst,WUNTRACED | WCONTINUED)) < 0){
perror("First waitpid error:\n");
}else{
if (WIFEXITED(statusFirst)) {
printf("First exited, status=%d\n", WEXITSTATUS(statusFirst));
} else if (WIFSIGNALED(statusFirst)) {
printf("First killed by signal %d\n", WTERMSIG(statusFirst));
} else if (WIFSTOPPED(statusFirst)) {
printf("First stopped by signal %d\n", WSTOPSIG(statusFirst));
} else if (WIFCONTINUED(statusFirst)) {
printf("First continued\n");
}
}
if((waitpid(childPidTwo,&statusSecond,WUNTRACED | WCONTINUED)) < 0){
perror("Second waitpid error:\n");
}
if (WIFEXITED(statusSecond)) {
printf("Second exited, status=%d\n", WEXITSTATUS(statusSecond));
} else if (WIFSIGNALED(statusSecond)) {
printf("Second killed by signal %d\n", WTERMSIG(statusSecond));
} else if (WIFSTOPPED(statusSecond)) {
printf("Second stopped by signal %d\n", WSTOPSIG(statusSecond));
} else if (WIFCONTINUED(statusSecond)) {
printf("Second continued\n");
}
exit(0);
return 0;
}
也許我有管+叉+ execvp是如何工作的,所以讓我告訴你,我在我的代碼正在做一個錯誤的認識:
- 我創建一個未命名的管道 - 無論是孩子的使用相同的管道
- 我會通過派生他們
- 創建兩個孩子的因爲我執行我的計劃是這樣的:
./pipeline [FIRST SYSTEM CALL] | [SECOND SYSTEM CALL]
或只給你一個例子:./pipeline echo Hello | wc -m
我關閉了管道的閱讀網站 - 然後調用
execvp(argv[1], &argv[1])
而這正是錯誤發生(我猜): 我從來沒有關閉寫入一側,直到第二個孩子呢,因爲如果成功execvp
將一去不復返。
而且我知道execvp
不會關閉打開的文件描述符(它可以通過使用fcntl
中的標誌來關閉,如What does the FD_CLOEXEC flag do?中所述)。
示例
讓我舉一個例子。
echo Hello | wc -m
輸出該結果
由於系統調用wc
(字數)計數在給定的String
這是正確的字符(-m
),因爲你好= 5 + 1(這是\n
或\0
我猜)這使得6。現在
,運行我的程序給出結果
或瞭解更多信息
echo hello | wc
輸出
1(行)1(字)6(字符)
而且./pipeline echo hello | wc
輸出
3(行)9(字)56(字符)
我搜索了好幾天,但我想不出它出。
任何想法?
非常感謝!
如果您使用'./pipeline echo hello | wc'來運行你的程序,那麼它不會做你認爲的那樣。你的程序看到'argv [1] == echo','[2] == hello'和_nothing else_。然後將程序的(組合)輸出傳送到'wc'中。爲了(完全)實現我認爲你想要做的事情,你需要轉義管道字符並在你的代碼中檢測它(所以你知道命令行的哪些部分要傳遞給每個子進程)。 – TripeHound
@TripeHound,我通過輸入./pipeline echo hello \ |手動逃過角色。 wc和它適用於我,除了第二個孩子在交互模式下啓動wc(等待輸入並按ctrl + d標記輸入結束)。這給了我1 1 6的正確結果。這意味着第一個孩子的輸入被忽略。有任何想法嗎 ? –