Как выполнить дочерние процессы в порядке C

Я написал код в C для подсчета строк слов и символов в файле. Как и команда wc . Код ниже и работает отлично.

 #include  #include  #include  #include  #include  #include  char* concat(char *s1, char *s2) { char *result = malloc(strlen(s1)+strlen(s2)+1); strcpy(result, s1); strcat(result, s2); return result; } int countLines(char *f){ FILE *file = fopen(f, "r"); int count = 0; char ch; while ((ch = fgetc(file)) != EOF){ if (ch == '\n') count++; } return count; } int countWords(char *f){ char buffer[1]; FILE *file = fopen(f, "r"); int countW = 0; enum states { WSP, WRD }; int state = WSP; char last = ' '; while (read(fileno(file),buffer,1) == 1 ) { if ( buffer[0]== ' ' || buffer[0] == '\t' || buffer[0]=='\n' ) { state = WSP; } else { if ( state == WSP ) { countW++; } state = WRD; } last = buffer[0]; } return countW; } int countChars(char *f){ FILE *file = fopen(f, "r"); int chars = 0; char ch; while ((ch = fgetc(file))){ if (ch == EOF) break; chars++; } return chars; } int main(int argc, char** argv) { int lineCount = 0; int wordCount = 0; int charCount = 0; int n = 3; int i,status; int pids[3]; char *theprogram = argv[0]; char *thefile = argv[1]; if ( argc !=2 ) { printf( "Help: %s filename\n", argv[0]); } else{ FILE *file = fopen( argv[1], "r"); if(file == 0){ char *sub = concat(theprogram, ": "); char *middle = concat(sub, thefile); perror(middle); } else{ for (i = 0; i < n; i++) { pids[i] = fork(); if ( pids[i] < 0) { perror("fork"); exit(-1); } else if (pids[i] == 0) { if (i==0){ lineCount = countLines(argv[1]); printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount); exit(0); } else if (i==1){ wordCount = countWords(argv[1]); printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount); exit(0); } else if (i==2){ charCount += countChars(argv[1]); printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount); exit(0); } } } for(i = 0; i < n; i++){ wait(NULL); } return 0; } } } 

У меня проблема:

Выход не всегда в порядке, например:

 //GOOD This is child proccess 1, and the number of lines is 5 This is child proccess 2, and the number of words is 5 This is child proccess 3, and the number of characters is 159 //BAD This is child proccess 1, and the number of lines is 5 This is child proccess 3, and the number of characters is 159 This is child proccess 2, and the number of words is 5 

Третий процесс заканчивается раньше второго. Как я могу предотвратить это?

Быстрый и грязный метод:

  } else if (pids[i] == 0) { usleep(i*1000); /* wait 1ms for child 1, 2ms for child 2,... */ if (i==0){ lineCount = countLines(argv[1]); printf("This is child proccess %d, and the number of lines is %d\n", i+1, lineCount); exit(0); } else if (i==1){ wordCount = countWords(argv[1]); printf("This is child proccess %d, and the number of words is %d\n", i+1, wordCount); exit(0); } else if (i==2){ charCount += countChars(argv[1]); printf("This is child proccess %d, and the number of characters is %d\n", i+1, charCount); exit(0); } } 

Другой способ – создать родительский процесс для создания трех UNIX-сокетов и прослушать их все с помощью select() или что-то в этом роде. Дети подключались и записывались в сокет, выходили, а затем родительский процесс печатал информацию, полученную в правильном порядке.

Разветвленные процессы будут выполняться асинхронно с кодом основной строки, поэтому, если вы хотите, чтобы они произошли по порядку, вам нужно использовать какой-то флаг. Это может быть семафор, мьютекс или задать логическое значение внутри условных выражений if.

Вам нужно будет использовать семафор или мьютекс для защиты восприимчивых данных от асинхронной записи, но это не проблема в этом контексте.

Я думаю, вы можете использовать stream, но не процесс, инициализируя некоторые глобальные переменные и присваивая значение переменных в дочернем streamе. контролируйте вывод в родительском streamе.