前提:
编写程序以向用户查询两个输入字符串.每个输入字符串应该是一个unix命令,允许使用参数.例如,输入1可以是ls -l,输入2可以是更多.然后程序将创建一个管道和两个子进程.第一个子进程将运行第一个输入中指定的命令.它将输出到管道而不是标准输出.第二个子进程将运行第二个输入中指定的命令.它将从管道输入而不是标准输入.父进程将等待其两个子进程完成,然后整个过程将重复.当输入’@’符号作为第一个命令时,执行将停止.这是我的代码:
编写程序以向用户查询两个输入字符串.每个输入字符串应该是一个unix命令,允许使用参数.例如,输入1可以是ls -l,输入2可以是更多.然后程序将创建一个管道和两个子进程.第一个子进程将运行第一个输入中指定的命令.它将输出到管道而不是标准输出.第二个子进程将运行第二个输入中指定的命令.它将从管道输入而不是标准输入.父进程将等待其两个子进程完成,然后整个过程将重复.当输入’@’符号作为第一个命令时,执行将停止.这是我的代码:
#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> int main(){ /* Program Termination Symbol */ const char terminate = '@'; /* String delimiter */ const char delimiter = ' '; /* Pipe file ID's */ int fileID[2]; /* Parent ID's */ int pid1,pid2; /* String token */ char * token,* token2; /* User input */ char * user_input,line[100]; user_input = (char *) malloc(100); /* Unix Commands */ char * command1[10],*command2[10]; for (int i=0; i<10; i++) { command1[i] = (char *)malloc(100*sizeof(char)); command2[i] = (char *)malloc(100*sizeof(char)); } /* Begin main program logic */ printf("Please enter the first command: \n"); user_input = gets(line); while (user_input[0] != terminate) { token = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token = strtok(user_input,&delimiter); } else { token = strtok(NULL,&delimiter); } if (token != NULL) { strcpy(command1[i],token); } else { command1[i] = 0; } } printf("Please enter the second command: \n"); user_input = gets(line); token2 = (char *) malloc(100*sizeof(char)); for (int i=0; i<10; i++) { if (i == 0) { token2 = strtok(user_input,&delimiter); } else { token2 = strtok(NULL,&delimiter); } if (token2 != NULL) { strcpy(command2[i],token2); } else { command2[i] = 0; } } /* Pipe and execute user commands */ /* Create pipe */ pipe(fileID); /* Create child processes */ pid1 = fork(); if (pid1 != 0) { pid2 = fork(); } /* First child process */ if (pid1 == 0) { dup2(fileID[1],1); execvp(command1[0],command1); } /* Second child process */ if (pid2 == 0) { dup2(fileID[0],0); execvp(command2[0],command2); } /* Wait for children to terminate */ wait(&pid1); wait(&pid2); /* Repeat */ printf("Please enter the first command: \n"); user_input = gets(line); } return 0; }
我遇到的问题是我的等待.如果我有两个,这对我来说是有意义的(每个孩子一个等待)然后程序在执行第一个管道后冻结.如果我删除了第二个等待,那么程序将再次开始循环,但是不会接受除了enter之外的键盘输入,并且会产生段错误.因此,无论是等待,输入和输出都是……
Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~
……然后它就锁起来了.如果我删除第二个等待,输入/输出是……
Please enter the first command: ls Please enter the second command: more Pipe Pipe.c Pipe.c~ Please enter the first command: (I hit enter,nothing else will work) Segmentation fault
有人有什么建议吗?这显然与等待这两个过程有关,但我对如何处理它感到茫然.
这个程序现在100%正常运行 – 非常感谢大家的帮助!堆栈溢出一直是互联网上最好的资源之一.非常感谢你花时间查看我的代码并给我你的建议.
解决方法
我同意torak所说的一切,但为了解决你的问题,你需要关闭你的管道.我认为你是“挂”,因为管道仍然是敞开的.
所以在父母中,就在“等待”之前,我会关闭管道.
close(fileID[0]); close(fileID[1]); wait(&pid_status); wait(&pid_status);
然后,在每个execvp之前,我会关闭孩子不会使用的管道的末端:
close(fileID[0]); dup2(fileID[1],1); execvp(command1[0],command1); close(fileID[1]); dup2(fileID[0],0); execvp(command2[0],command2);
这应该解决你的问题.除了torak提出的建议之外,我还建议使用fgets而不是gets来防止缓冲区溢出.