Есть ещё один вид взаимодействия процессов в unix, каналы.
Рассмотрим на примере как это работает.
Программа parent создает канал с помощью системного вызова pipe(), далее приводит дескрипторы чтения и записи к символьному типу, создает форков(новый процесс, выполняющий ту же самую программу, у потомков fork() возвращает 0), форки вызывают программы src и dst, передавая им дескрипторы записи и чтения соответственно, джёт завершения форков и завершается сама. Программа src передает сообщение с помощью write(), используя дескриптор для записи в канал, который передан ей как аргумент и завершается. Программа dst получает сообщение с помощью read() и выводит его на экран, используя write(). Листинги программ:
Рассмотрим на примере как это работает.
Программа parent создает канал с помощью системного вызова pipe(), далее приводит дескрипторы чтения и записи к символьному типу, создает форков(новый процесс, выполняющий ту же самую программу, у потомков fork() возвращает 0), форки вызывают программы src и dst, передавая им дескрипторы записи и чтения соответственно, джёт завершения форков и завершается сама. Программа src передает сообщение с помощью write(), используя дескриптор для записи в канал, который передан ей как аргумент и завершается. Программа dst получает сообщение с помощью read() и выводит его на экран, используя write(). Листинги программ:
/*Файл parent.c: порождает двух форков, ждет их завершения, закрывает канал и завершается*/ #include <stdio.h> #include <unistd.h> #include <sys/wait.h> #define STR_SIZE 32 int main(void) { int pf[2]; int pid1, pid2; char spf[2][STR_SIZE]; /*Создание канала. Чтение идет через pf[0], запись - через pf[1]*/ if(pipe(pf) == -1){ fprintf(stderr, "pipe() error\n"); return 1; } /*Запись дескрипторов для последующей передачи в качестве параметров программам, осуществляющим запись и чтение*/ sprintf(spf[0], "%d", pf[0]); sprintf(spf[1], "%d", pf[1]); /*Первый форк вызывает программу src. В качестве параметра передается дескриптор для записи*/ if((pid1 = fork()) == 0){ close(pf[0]); execl("./src", "src", spf[1], NULL); fprintf(stderr, "exec() [src] error\n"); return 1; } /*Второй форк вызывает программу dst. В качестве параметра передается дескриптор для чтения*/ if((pid2 = fork()) == 0){ close(pf[1]); execl("./dst", "dst", spf[0], NULL); fprintf(stderr, "exec() [dst] error\n"); return 1; } /*Ждем и завершаемся*/ waitpid(pid1, NULL, 0); close(pf[0]); close(pf[1]); waitpid(pid2, NULL, 0); return 0; }
/*Листинг src.c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #define PP_MESSAGE "Hello World\n" #define WAIT_SECS 5 int main(int argc, char ** argv) { int i, fd; if(argc < 2){ fprintf(stderr, "src: Too few arguments\n"); return 1; } fd = atoi(argv[1]); fprintf(stderr, "Wait please"); for(i = 0; i < WAIT_SECS; i++, sleep (1)) fprintf(stderr, "."); fprintf(stderr, "\n"); if(write (fd, PP_MESSAGE, strlen(PP_MESSAGE)) == -1){ fprintf(stderr, "src: write() error\n"); return 1; } close(fd); return 0; }
/*Листинг dst,c*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char ** argv) { int fd; char ch; if(argc < 2){ fprintf(stderr, "dst: Too few arguments\n"); return 1; } fd = atoi(argv[1]); while(read(fd, &ch, 1) > 0) write(1, &ch, 1); close(fd); return 0; }Вот что получается в результате наших махинаций:
![]() |
Системный вызов pipe() |
Комментариев нет:
Отправить комментарий