Во-первых, вы можете создать более привлекательный цикл выбора () следующим образом:
while (newfds = readfds, select(n, &newfds, NULL, NULL, NULL))
Теперь к вашей проблеме. Как видно из приведенного выше кода, вы сообщаете родителю каждый раз, когда select () разблокирует , что может происходить более одного раза за процесс карты. select()
может разблокировать и запускать весь остальной код в цикле каждый раз, когда любой процессов вашей карты отправляет данные процессу сокращения. Даже если это половина ответа.
Если вы хотите отправить сигнал, как только вы все уменьшите, вам нужно реализовать некоторую логику, чтобы обнаружить, что все процессы выполнены, завершить цикл, а затем (вне цикла) подать сигнал родителю.
Изменить: попробуйте что-то вроде этого (я удалил некоторые детали вашего кода, чтобы сделать пример более понятным).
void reduce() {
int i, answer, waiting, ret;
fd_set read_set, selected_set;
FD_ZERO(&read_set);
for (i = 0; i < maps_nr; i++)
FD_SET(fd_maps_to_reduce[i][READ], &read_set);
waiting = maps_nr; /* how many answers are we expecting? */
while(waiting > 0 &&
selected_set = read_set,
select(FD_SETSIZE, &selected_set, NULL, NULL, NULL)) {
for (i = 0; i < maps_nr; i++) {
if (FD_ISSET(fd_maps_to_reduce[i][READ], &set)) {
close(fd_maps_to_reduce[i][WRITE]);
/* read your result. Once you have it: */
FD_CLR(fd_maps_to_reduce[i][READ], &read_set);
/* Now you won't wait for that pipe to produce data. */
waiting--;
}
}
}
/* Now you are out of the select loop. Signal, or whatever. */
}
edit 2: и, кстати, ваш результат может быть напечатан 0, потому что вы имеете дело с различными процессами здесь. Процесс сокращения имеет свою собственную копию переменной результата, она не изменит копию в основном процессе. Вы должны IPC это, может быть, другой канал, если уже написал код для этого.