Программирование для Linux. Профессиональный подход
Шрифт:
помещаются в массив FDS. */
pipe(fds);
/* порождение дочернего процесса. */
pid = fork;
if (pid == (pid_t)0) {
FILE* stream;
/* Это дочерний процесс. Закрываем копию входного конца
канала. */
close(fds[1]);
/* Приводим дескриптор выходного конца канала к типу FILE*
и читаем данные из канала. */
stream = fdopen(fds[0], "r");
reader(stream);
close(fds[0]);
} else {
/*
Это родительский процесс. */
FILE* stream;
/* Закрываем копию выходного конца канала. */
close(fds[0]);
/* Приводим дескриптор входного конца канала к типу FILE*
и записываем данные в канал. */
stream = fdopen(fds[1], "w");
writer("Hello, world.", 5, stream);
close(fds[1]);
}
return 0;
}
Сначала в программе объявляется массив
fds
, состоящий из двух целых чисел. Функция pipe
создает канал и помещает в массив дескрипторы входного и выходного концов канала. Затем функция fork
порождает дочерний процесс. После закрытия выходного конца канала родительский процесс начинает записывать строки в канал. Дочерний процесс читает строки из канала, предварительно закрыв его входной конец. Обратите внимание на то. что в функции
writer
родительский процесс принудительно "выталкивает" буфер канала, вызывая функцию fflush
. Без этого строка могла бы ""застрять" в буфере и отправиться в канал только после завершения родительского процесса. При вызове команды
ls | less
функция fork выполняется дважды: один раз — для дочернего процесса ls
, второй раз — для дочернего процесса less
. Оба процесса наследуют копии дескрипторов канала, поэтому могут общаться друг с другом. О соединении несвязанных процессов речь пойдет ниже, в разделе 5.4.5, "Каналы FIFO". 5.4.3. Перенаправление стандартных потоков ввода, вывода и ошибок
Часто требуется создать дочерний процесс и сделать один из концов канала его стандартным входным или выходным потоком. В этом случае на помощь приходит функция
dup2
, которая делает один файловый дескриптор равным другому. Вот как, например, можно связать стандартный входной поток с файлом fd
: dup2(fd, STDIN_FILENO);
Символическая константа
STDIN_FILENO
представляет дескриптор файла, соответствующий стандартному потоку ввода (значение этого дескриптора равно 0). Показанная функция закрывает входной поток, а затем открывает его под видом файла fd
. Оба дескриптора (0 и fd
) будут указывать на одну и ту же позицию в файле и иметь одинаковый набор флагов состояния, т.е. дескрипторы станут взаимозаменяемыми. Программа, представленная в листинге 5.8, с помощью функции
dup2
соединяет выходной. Конец канала со входом команды sort
. [16]
fork
на два процесса. Родительский процесс записывает в канал различные строки, а дочерний процесс соединяет выходной конец канала со своим входным потоком, после чего запускает команду sort
. Листинг 5.8. (dup2.c) Перенаправление выходного потока канала с помощью функции
dup2
16
Команда
sort
читает строки текста ил стандартного входного потока, сортирует их в алфавитном порядке и записывает в стандартный выходной поток. #include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main {
int fds[2];
pid_t pid;
/* Создание канала. Дескрипторы обоих концов канала
помещаются в массив FDS. */
pipe (fds);
/* Создание дочернего процесса. */
pid = fork;
if (pid == (pid_t)0) {
/* Это дочерний процесс. Закрываем копию входного конца
канала */
close(fds[1]);
/* Соединяем выходной конец канала со стандартным входным
потоком. */
dup2(fds[0], STDIN_FILENO);
/* Замещаем дочерний процесс программой sort. */
execlp("sort", "sort", 0);
} else {
/* Это родительский процесс. */
FILE* stream;
/* Закрываем копию выходного конца канала. */
close(fds[0]);
/* Приводим дескриптор входного конца канала к типу FILE*
и записываем данные в канал. */
stream = fdopen(fds[1], "w");
fprintf(stream, "This is a test.\n");
fprintf(stream, "Hello, world.\n");
fprintf(stream, "My dog has fleas.\n");
fprintf(stream, "This program is great.\n");
fprintf(stream, "One fish, two fish.\n");
fflush(stream);
close(fds[1]);
/* Дожидаемся завершения дочернего процесса. */
waitpid(pid, NULL, 0);
}
return 0;
}
5.4.4. Функции popen и pclose
Поделиться:
Популярные книги
Газлайтер. Том 10
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
На границе империй. Том 7. Часть 2
8. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
6.13
рейтинг книги
Звездная Кровь. Изгой
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Хозяин Теней 4
4. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Картофельное счастье попаданки
Фантастика:
фэнтези
5.00
рейтинг книги
Экзорцист: Проклятый металл. Жнец. Мор. Осквернитель
Фантастика:
фэнтези
героическая фантастика
5.50
рейтинг книги
Доктора вызывали? или Трудовые будни попаданки
Фантастика:
юмористическая фантастика
попаданцы
5.00
рейтинг книги
Метатель
1. Метатель
Фантастика:
боевая фантастика
попаданцы
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Моя на одну ночь
Любовные романы:
современные любовные романы
короткие любовные романы
5.50
рейтинг книги
Чехов. Книга 2
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Хозяин Теней 2
2. Безбожник
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Сумеречный стрелок 7
7. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Жизнь под чужим солнцем
Детективы:
прочие детективы
9.10
рейтинг книги
Красноармеец
1. Красноармеец
Фантастика:
боевая фантастика
попаданцы
4.60