Сложная часть того, что вы пытаетесь сделать, - это создание конвейера. Вы можете просто сделать так, чтобы оболочка сделала это для вас ...
$ ./makenumbers | ./addnumbers | ./printresult
но это скучно, а? И вам нужно иметь три исполняемых файла. Итак, давайте посмотрим, что делают эти вертикальные полосы на уровне C.
Вы создаете канал с помощью системного вызова pipe
. Вы переназначаете стандартный ввод / вывод с помощью dup2
. Вы создаете новые процессы с fork
, и вы ждете, пока они завершатся с waitpid
. Программа для настройки всего этого будет выглядеть примерно так:
int
main(void)
{
pid_t children[2];
int pipe1[2], pipe2[2];
int status;
pipe(pipe1);
pipe(pipe2);
children[0] = fork();
if (children[0] == 0)
{
/* in child 0 */
dup2(pipe1[1], 1);
generate_two_numbers_and_write_them_to_fd_1();
_exit(0);
}
children[1] = fork();
if (children[1] == 0)
{
/* in child 1 */
dup2(pipe1[0], 0);
dup2(pipe2[1], 1);
read_two_numbers_from_fd_0_add_them_and_write_result_to_fd_1();
_exit(0);
}
/* parent process still */
dup2(pipe2[0], 0);
read_a_number_from_fd_0_and_print_it();
waitpid(children[0], &status, 0);
waitpid(children[1], &status, 0);
return 0;
}
Обратите внимание:
- Я исключил всю обработку ошибок, потому что это сделало бы программу примерно втрое длиннее. Ваш инструктор хочет, чтобы вы включили обработку ошибок.
- Точно так же я пропустил проверку статуса выхода детей; ваш инструктор также хочет, чтобы вы это проверили.
- Вам не нужно
dup2
звонков; Вы можете просто передать номера канала в вызовы подпрограмм. Но если бы у вас был exec
- новый двоичный файл в дочернем файле, что более типично, они вам понадобятся. Тогда вам также придется позаботиться о том, чтобы все файловые дескрипторы с номерами от 3 и выше были закрыты.
- Существует причина, по которой я использую
_exit
вместо exit
. Попробуйте выяснить, что это такое.
- Вам нужно использовать
read
и write
вместо вызовов stdio.h в подпрограммах, вызываемых из дочерних процессов. Причина связана с тем, что я использую _exit
.