Программа, представленная в листинге 5.8, с помощью функции dup2()соединяет выходной. Конец канала со входом команды sort. [16] Команда sort читает строки текста ил стандартного входного потока, сортирует их в алфавитном порядке и записывает в стандартный выходной поток.
После создания канала программа "делится" функцией fork()на два процесса. Родительский процесс записывает в канал различные строки, а дочерний процесс соединяет выходной конец канала со своим входным потоком, после чего запускает команду sort.
Листинг 5.8. ( dup2.c ) Перенаправление выходного потока канала с помощью функции dup2()
#include
#include
#include
#include
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()
Каналы часто используются для передачи данных программе, выполняющейся как подпроцесс (или приема данных от нее). Специально для этих целей предназначены функции popen()и pclose(), устраняющие необходимость в вызове функций pipe(), dup2(), exec()и fdopen().
Сравните листинг 5.9 с предыдущим примером (листинг 5.8).
Листинг 5.9. ( popen.c ) Использование функций popen()и pclose()
#include
#include
int main() {
FILE* stream = popen("sort", "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");
return pclose(stream);
}
Функция popen()создает дочерний процесс, в котором выполняется команда sort. Один этот вызов заменяет вызовы функций pipe(), fork(), dup2()и execlp(). Второй аргумент, "w", указывает на то, что текущий процесс хочет осуществлять запись в дочерний процесс. Функция popen()возвращает указатель на один из концов канала; второй конец соединяется со стандартным входным потоком дочернего процесса. Функция pclose()закрывает входной поток дочернего процесса, дожидается его завершения и возвращает код статуса.
Первый аргумент функции popen()является командой интерпретатора, выполняемой в подпроцессе /bin/sh. Интерпретатор просматривает переменную среды PATH, чтобы определить, где следует искать команду. Если второй аргумент равен "r", функция возвращает указатель на стандартный выходной поток дочернего процесса, чтобы программа могла читать данные из него. Если второй аргумент равен "w", функция возвращает указатель на стандартный входной поток дочернего процесса, чтобы программа могла записывать данные в него. В случае ошибки возвращается пустой указатель.
Функция pclose()закрывает поток, указатель на который был возвращен функцией popen(), и дожидается завершения дочернего процесса.
Файл FIFO (First-In, First-Out — первым пришел, первым обслужен) — это канал, у которого есть имя в файловой системе. Любой процесс может открыть и закрыть такой файл. Процессы, находящиеся на противоположных концах канала, не обязаны быть связанными друг с другом. FIFO-файлы называют именованными каналами .
FIFO-файл создается с помощью команды mkfifo. Путь к файлу указывается в командной строке, например:
% mkfifo /tmp/fifo
% ls -l /tmp/fifo
prw-rw-rw- 1 samuel users 0 Jan 16 14:04 /tmp/fifo
Читать дальше