Pipe
為什麼程序退出後 exec 列印它的輸出?
我正在編寫一個程序來將一個命令傳遞給另一個命令。輸入將來自命令行:
$ ./a.out ls '|' wc c2 PID 6804 c1 PID 6803 PARENT PID 6802 $ 2 2 17
為什麼提示返回後輸出列印。有什麼辦法可以防止這種情況發生嗎?
這是我寫的程式碼:
#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main(int argc, char * argv[]) { if(argc <= 1 ) { printf("ERROR: No arguments passed\n"); printf("USAGE: ./pipe <command 1> | <command 2>\n"); return 1; } char * cmd1[50]; char * cmd2[50]; int cmd1_arg = 0; int cmd2_arg = 0; int pipe_num = 0; for(int cla = 1; cla<argc; cla++) { if( !strcmp(argv[cla],"|") ) pipe_num++; else if(pipe_num == 0) cmd1[cmd1_arg++] = argv[cla]; else if(pipe_num == 1) cmd2[cmd2_arg++] = argv[cla]; } cmd1[cmd1_arg] = (char *)NULL; cmd2[cmd2_arg] = (char *)NULL; if(pipe_num != 1) { printf("ERROR: Insufficient arguments passed\n"); printf("USAGE: ./pipe <command 1> | <command 2>\n"); return 1; } int pipe_fd[2]; pipe(pipe_fd); pid_t pid = fork(); if(pid == -1) { perror("FORK FAILED"); return 1; } if(pid != 0) { pid_t cmd_pid = fork(); if(cmd_pid == -1) { perror("FORK FAILED"); return 1; } if(cmd_pid != 0) { waitpid(pid,NULL,0); waitpid(cmd_pid,NULL,WNOHANG); printf("PARENT PID %d\n",getpid()); } if(cmd_pid == 0) { printf("c2 PID %d\n",getpid()); close(pipe_fd[1]); int stdin_fd = dup(0); close(0); dup(pipe_fd[0]); if(execvp(cmd2[0],cmd2) == -1 ) perror("CMD2 FAIL"); close(0); dup(stdin_fd); } } if(pid == 0) { printf("c1 PID %d\n",getpid()); close(pipe_fd[0]); int stdout_fd = dup(1); close(1); int test = dup(pipe_fd[1]); if( execvp(cmd1[0],cmd1) == -1 ) perror("CMD1 FAIL"); close(1); dup(stdout_fd); } return 0; }
你有:
waitpid(cmd_pid,NULL,WNOHANG);
通過包含該
WNOHANG
選項,您是在告訴waitpid()
如果程序尚未終止,則不要等待程序終止。我的猜測是你添加了它,因為如果你不包含它,你的程序就會掛起。那是因為原始父級仍然有一個打開的文件描述符到管道的寫入端,所以讀取過程仍然被阻塞等待該管道上的輸入。
這是您的程序的修訂版本,它關閉了管道文件描述符,並且不使用
WNOHANG
.#include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main(int argc, char *argv[]) { if (argc <= 1) { printf("ERROR: No arguments passed\n"); printf("USAGE: ./pipe <command 1> | <command 2>\n"); return 1; } char *cmd1[50]; char *cmd2[50]; int cmd1_arg = 0; int cmd2_arg = 0; int pipe_num = 0; for (int cla = 1; cla < argc; cla++) { if (!strcmp(argv[cla], "|")) { pipe_num++; } else if (pipe_num == 0) { cmd1[cmd1_arg++] = argv[cla]; } else if (pipe_num == 1) { cmd2[cmd2_arg++] = argv[cla]; } } cmd1[cmd1_arg] = NULL; cmd2[cmd2_arg] = NULL; if (pipe_num != 1) { printf("ERROR: Insufficient arguments passed\n"); printf("USAGE: ./pipe <command 1> | <command 2>\n"); return 1; } int pipe_fd[2]; if (pipe(pipe_fd) < 0) { perror("pipe"); return 1; } const pid_t pid = fork(); if (pid < 0) { perror("fork"); return 1; } else if (pid != 0) { const pid_t cmd_pid = fork(); if (cmd_pid < 0) { perror("fork"); return 1; } else if (cmd_pid != 0) { printf("PARENT PID %d\n", getpid()); close(pipe_fd[0]); close(pipe_fd[1]); if (waitpid(pid, NULL, 0) < 0) { perror("waitpid"); } if (waitpid(cmd_pid, NULL, 0) < 0) { perror("waitpid"); } } else { printf("c2 PID %d\n", getpid()); if (dup2(pipe_fd[0], STDIN_FILENO) < 0) { perror("dup2"); return 1; } close(pipe_fd[0]); close(pipe_fd[1]); if (execvp(cmd2[0], cmd2) < 0) { perror("CMD2 FAIL"); return 1; } } } else { printf("c1 PID %d\n", getpid()); if (dup2(pipe_fd[1], STDOUT_FILENO) < 0) { perror("dup2"); return 1; } close(pipe_fd[0]); close(pipe_fd[1]); if (execvp(cmd1[0], cmd1) < 0) { perror("CMD1 FAIL"); return 1; } } return 0; }
執行這個程序給了我:
./a.out echo 1 2 3 '|' wc PARENT PID 20412 c1 PID 20413 c2 PID 20414 1 3 6 $