STDIN からの入力を単語に解析し、numsorts 変数で指定された多数の並べ替えプロセスを生成し、単語をラウンドロビン方式で各並べ替えプロセスにパイプし、並べ替えの出力を送信する C プログラムを作成しています。 STDOUTへ。
指定された並べ替えプロセスの数が 1 の場合、プログラムは希望どおりに動作し、正常に終了しますが、並べ替えプロセスの数が 1 より大きい場合、並べ替えの子プロセスは終了せず、プログラムはそれらを待機してスタックします。これの最も奇妙な部分は、別のターミナル ウィンドウを開いて 1 を除くすべての子を殺すと、最後の子がすぐに単独で死に、プログラムが正常に終了することです。
パーサーのコードは次のとおりです (パイプ ファイル記述子は 2 次元配列に格納されます)。
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);
}