我想在c中編寫一個簡單的shell。現在我試圖讓管道工作。我有一個結構c
我敢送入這個功能,它包含存儲管文件描述符pipfd
的位置,並且包含了每個命令c->type
的結束標記信息(這可以是| || & & &等)。 CommandPrev
只是跟蹤最後一個命令,所以我可以看到命令之前是否有管道標籤。爲什麼我的管道不能互相交談?
我完成這項工作後,我給孩子的PID(返回值)waitpid
伺候我execvp
稱爲當我運行的命令,例如echo foo | echo bar
我得到bar
作爲輸出完全一樣的命令我期望,一切都很好。我的問題是,當我嘗試運行任何實際上使用來自管道前半部分的輸入的命令時,一切都會卡住。如果我運行類似echo foo | wc -c
的東西,我不會得到任何輸出,它會永遠掛起。
我可以看到這個功能對這些類型的命令完成,因爲我打印當它返回。發生的事情是,我用execvp調用的命令從來沒有發生,所以我的waitpid永遠等待。
我認爲不知我的我管的兩端之間的連接斷開。任何一件事都不會被寫入,或者它們永遠不會被讀取,或者管道的接收端從未意識到寫入方已經完成,並且只是等待着永遠。我立即在所有管道上關閉,所以我傾向於懷疑它的最後一個......但我真的不知道如何去測試這三種情況中的任何一種。
這是我的代碼:
pid_t start_command(command* c, pid_t pgid) {
(void) pgid;
// If its a pipe token, create a shared pipe descriptor
if (c->type == TOKEN_PIPE){
pipe(c->pipefd);
}
// Fork a child process, run the command using `execvp`
pid_t child = fork();
if (child == 0) {
// writing side of the pipe
if (c->type == TOKEN_PIPE){
dup2(c->pipefd[WRITE_SIDE], STDOUT_FILENO);
close(c->pipefd);
}
// receiving side of the pipe
else if (commandPrev->type == TOKEN_PIPE){
dup2(commandPrev->pipefd[READ_SIDE], STDIN_FILENO);
close(commandPrev->pipefd);
}
// run the command
if (execvp(c->argv[0], c->argv) == -1) {
// fork failed
exit(-1);
}
}
else{
// clean up, clean up, everybody, everywhere
if (commandPrev->type == TOKEN_PIPE){
close(commandPrev->pipefd);
}
}
printf("return %i\n", getpid());
return child;
}
謝謝!
檢查您的系統調用錯誤,它們不會自動打印。 'close(c-> pipefd);'似乎試圖關閉一個數組。 –
對於殼牌規格和語言的知識將幫助人們回答的問題,請使用'shell'標籤。人們爲學校編寫玩具殼這一點非常非常少見。 –
@CharlesDuffy我的壞!我不知道,對不起 – Twiigs