我正在编写一个C程序,它将STDIN的输入解析为单词,生成numsorts变量指定的多个排序进程,以循环方式将单词传递给每个排序进程,并发送输出STDOUT的种类。
如果指定的排序进程数为1,我的程序将按照需要工作并干净地退出,但如果排序进程数大于1,则排序子进程不会死,并且我的程序会等待它们。对我来说,最奇怪的部分是,如果我打开一个单独的终端窗口并杀死除1之外的所有孩子,最后一个孩子会立即自行死亡并且程序干净利落。
这是我的解析器代码(管道文件描述符存储在一个二维数组中):
void RRParser(int numsorts, int **outPipe){ //Round Robin parser
int i;
char word[MAX_WORD_LEN];
//Close read end of pipes
for(i = 0; i < numsorts; i++){
closePipe(outPipe[i][0]);
}
//fdopen() all output pipes
FILE *outputs[numsorts];
for(i=0; i < numsorts; i++){
outputs[i] = fdopen(outPipe[i][1], "w");
if(outputs[i] == NULL)
printf("Error: could not create output stream.\n");
}
//Distribute words to them
i = 0;
while(scanf("%[^,]%*c,", word) != EOF){
strtoupper(word);
fputs(word, outputs[i % numsorts]); //round robin
fputs("\n", outputs[i % numsorts]); //sort needs newline
i++;
}
//Flush the streams:
for(i=0; i < numsorts; i++){
if(fclose(outputs[i]) == EOF)
printf("Error closing stream.\n");
}
}
这是生成排序过程的代码(PukeAndExit()只打印出错误消息并退出):
int *spawnSorts(int numsorts, int **inPipe){
//returns an array containing all the PIDs of the child processes
//Spawn all the sort processes
pid_t pid;
int i;
int *processArray = (int *)malloc(sizeof(int) * numsorts);
for(i = 0; i < numsorts; i++){
switch(pid = fork()){
case -1: //oops case
PukeAndExit("Forking error\n");
case 0: //child case
//Bind stdin to read end of pipe
closePipe(inPipe[i][1]); //close write end of input pipe
if(inPipe[i][0] != STDIN_FILENO){ //Defensive check
if(dup2(inPipe[i][0], STDIN_FILENO) == -1)
PukeAndExit("dup2 0");
closePipe(inPipe[i][0]); //Close duplicate pipe
}
execlp("sort", "sort", (char *)NULL);
break;
default: //parent case
processArray[i] = pid;
}
}
return processArray;
}
在main()的末尾,这是等待排序进程死的代码:
for(i=0; i<numsorts; i++){ //wait for child processes to die.
wait(NULL);
}
答案 0 :(得分:0)
没关系,我明白了。该bug实际上是在我生成管道的函数中。一旦我切换到我的spawnSorts过程中创建管道,一切都有效。以前,我在一个单独的函数中生成一个管道数组。我不确定为什么现在这样有效但是确实如此。
旧的generatePipes函数:
int **generatePipesArray(int numpipes){ //returns a 2-dimensional array of pipes
int **pipesArray = (int **) malloc(sizeof(int *) * (numpipes));
int i;
for(i = 0; i < numpipes; i++){
pipesArray[i] = (int *) malloc(sizeof(int) * 2);
createPipe(pipesArray[i]);
}
return(pipesArray);
}
新功能:
int **generatePipesArray(int numpipes){ //returns an empty 2-dimensional array
int **pipesArray = (int **) malloc(sizeof(int *) * (numpipes));
int i;
for(i = 0; i < numpipes; i++){
pipesArray[i] = (int *) malloc(sizeof(int) * 2);
//not creating pipes here anymore
}
return(pipesArray);
}
添加到spawnSorts的代码:
int *spawnSorts(int numsorts, int **inPipe, int **outPipe){
//returns an array containing all the PIDs of the child processes
//Spawn all the sort processes
pid_t pid;
int i;
int *processArray = (int *)malloc(sizeof(int) * numsorts);
for(i = 0; i < numsorts; i++){
//new code here:
createPipe(inPipe[i]);