管道流和子进程

我需要编写我的管道流。 我的程序应该获取另一个程序的名称并调用它们,第一个程序应该从第一个输出的stdin读取第二个等等。 最后一个程序在stdout中打印结果。 问题是它不起作用。 当我把这个程序称为另外两个简单程序时(它们都是读取x并打印2 * x,而它可以读取),并给它一些数据,我想我应该立即得到结果,但我没有。 更重要的是,当我给它文件结束它没有反应。 不要注意safe_ *函数,它们与标准相同,但检查错误。 帮帮我,请=)

#include  #include  #include  #include  #include  #include  #include  #include "error.h" #include "safe_functions.h" void call(const char *filename, int in_descr, int out_descr, pid_t *sons, int n) { sons[n] = safe_fork(); if(sons[n] == 0) { safe_dup2(in_descr, STDIN_FILENO); safe_dup2(out_descr, STDOUT_FILENO); safe_execv(filename, (char **)NULL); } } int find_num(pid_t * sons, int n, pid_t id) { for(int i=0; i<n; i++) if(sons[i] == id) return i; return -1; } int main(int argc, const char ** argv) { int **descr; descr = (int**)safe_malloc(argc*sizeof(int*)); for(int i=0; i<argc; i++) descr[i] = (int*) safe_malloc(2*sizeof(int)); for(int i=1; i+1<argc; i++) safe_pipe(descr[i]); descr[0][0] = 0; descr[argc-1][1] = 1; pid_t *sons = safe_malloc((argc-1) * sizeof(pid_t)); for(int i=1; i<argc; i++) call(argv[i], descr[i-1][0], descr[i][1], sons, i-1); int status; pid_t id; while(1) { id = safe_wait(&status); if(id == -1) break; if(WIFEXITED(status)) { int num = find_num(sons, argc-1, id); safe_close(descr[num][0]); safe_close(descr[num+1][1]); continue; } if(WIFSIGNALED(status)) { int num = find_num(sons, argc-1, id); fatal_error("Process was teminated by a signal", argv[num+1], WEXITSTATUS(status)); } } free(sons); for(int i=0; i<argc; i++) free(descr[i]); free(descr); } 

你没有足够的电话close() ! 父级必须关闭所有管道副本。 在将相关管道描述符复制到标准输入和输出之后,子节点也必须关闭每个管道描述符。 否则,进程永远不会获得EOF,因为有一个进程可以写入管道。

SSCCE( 简短,自包含,正确的例子 )

此代码使用我的stderr.hstderr.c代码代替您的error.h (如果您需要代码,请与我联系 – 请参阅我的个人资料)。 它写出了safe_*函数 – 或者至少是我对它们的实现。

dump_fds()函数报告在0-19范围内打开的文件描述符,这对于这个和大多数程序来说已经足够了; 更复杂的版本与sysconf()以确定要检查的文件描述符的数量,但数量通常比使用的数量大得多(例如256或更大)。 我用它作为一种简单的方法来检查应该关闭的所有文件描述符是否都已关闭。

有相当多的调试输出。 对execv()的调用提供了一个适当的参数列表。

 #include  #include  #include  #include  #include  #include  #include  #include  //#include "error.h" //#include "safe_functions.h" #include "stderr.h" extern pid_t safe_fork(void); extern void safe_dup2(int old_fd, int new_fd); extern void safe_execv(const char *prog, char **argv); extern void safe_pipe(int *pipe_fds); extern void *safe_malloc(size_t size); extern int safe_wait(int *status); extern void safe_close(int fd); /* Report on open file descriptors (0..19) in process */ static void dump_fds(void) { struct stat b; char buffer[32]; sprintf(buffer, "%d: ", getpid()); char *str = buffer + strlen(buffer); for (int i = 0; i < 20; i++) *str++ = (fstat(i, &b) == 0) ? 'o' : '-'; *str++ = '\n'; *str = '\0'; fputs(buffer, stderr); } static void close_pipes(int **descr, int argc) { for (int i = 0; i < argc; i++) { for (int j = 0; j < 2; j++) { if (descr[i][j] > 1) { err_remark("close %d\n", descr[i][j]); safe_close(descr[i][j]); } } } } static void call(char *filename, int in_descr, int out_descr, pid_t *sons, int n, int **descr, int argc) { sons[n] = safe_fork(); if (sons[n] == 0) { err_remark("call: %s\n", filename); char *argv[2] = { filename, NULL }; err_remark("dup2(%d, %d)\n", in_descr, STDIN_FILENO); err_remark("dup2(%d, %d)\n", out_descr, STDOUT_FILENO); safe_dup2(in_descr, STDIN_FILENO); safe_dup2(out_descr, STDOUT_FILENO); close_pipes(descr, argc); dump_fds(); safe_execv(argv[0], argv); } } static int find_num(pid_t *sons, int n, pid_t id) { for (int i=0; i 

示例输出

 $ ./pipes-15845060 /bin/ps /usr/bin/sort /bin/cat 12096: ooo----------------- pipes-15845060: pid=12096: pipe: 3, 4 pipes-15845060: pid=12096: pipe: 5, 6 pipes-15845060: pid=12096: Command: /bin/ps pipes-15845060: pid=12096: Command: /usr/bin/sort pipes-15845060: pid=12096: Command: /bin/cat pipes-15845060: pid=12096: close 3 pipes-15845060: pipes-15845060: pid=12098: pid=12096: close 4 pipes-15845060: pid=12096: close 5 pipes-15845060: pid=12096: close 6 call: /bin/ps pipes-15845060: pid=12098: dup2(0, 0) pipes-15845060: pid=12098: dup2(4, 1) pipes-15845060: pid=12099: call: /usr/bin/sort pipes-15845060: pid=12099: dup2(3, 0) pipes-15845060: pid=12099: dup2(6, 1) pipes-15845060: pid=12098: pipes-15845060: pid=12099: close 3 pipes-15845060: pid=12099: close 4 pipes-15845060: pid=12099: close 5 pipes-15845060: pid=12099: close 6 12099: ooo----------------- close 3 pipes-15845060: pid=12098: close 4 pipes-15845060: pid=12098: close 5 pipes-15845060: pid=12098: close 6 12098: ooo----------------- pipes-15845060: pid=12100: call: /bin/cat pipes-15845060: pid=12100: dup2(5, 0) pipes-15845060: pid=12100: dup2(1, 1) pipes-15845060: pid=12100: close 3 pipes-15845060: pid=12100: close 4 pipes-15845060: pid=12100: close 5 pipes-15845060: pid=12100: close 6 12100: ooo----------------- pipes-15845060: pid=12096: wait: pid 12098, status 0x0000 563 ttys000 0:00.03 -sh 568 ttys001 0:00.03 -sh 578 ttys003 0:00.03 -sh 587 ttys002 0:00.03 -sh 588 ttys005 0:00.15 -sh 589 ttys004 0:00.20 -sh PID TTY TIME CMD 12096 ttys004 0:00.00 ./pipes-15845060 /bin/ps /usr/bin/sort /bin/cat 12097 ttys004 0:00.00 sed /./s/^/ / 12099 ttys004 0:00.00 /usr/bin/sort 12100 ttys004 0:00.00 /bin/cat pipes-15845060: pid=12096: wait: pid 12100, status 0x0000 pipes-15845060: pid=12096: wait: pid 12099, status 0x0000 pipes-15845060: pid=12096: wait: pid -1, status 0x0000 $