Листинг 26.1. Родительский процесс
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
char buff[1024]={0};
FILE * cp; // cp - child process - дочерний процесс
int status;
// Открываем канал. Дочерний процесс - /usr/bin/child
cp=popen('/usr/bin/child', 'w');
if (!cp) {
printf('He могу открыть канал.
');
exit(1);
}
printf('Введите информацию для передачи дочернему процессу ');
// читаем ввод пользователя
fgets(buff, sizeof(buff), stdin);
// передаем данные дочернему процессу
fprintf(cp, '%s
', buff);
// 'выталкиваем' содержимое буфера в канал
fflush(cp);
// закрываем канал и проверяем состояние вызова pclose()
status=pclose(cp);
if (!WIFEXITED(status))
printf('ошибка при закрытии канала
');
printf('Завершение работы родительского процесса
');
return 0;
}
Листинг 26.2. Дочерний процесс — исходный код /usr/bin/child
#include <stdio.h>
int main() {
char buff[1024]={0};
fgets(buff, sizeof(buff), stdin);
printf('Прочитал со стандартного ввода: %s
', buff);
printf('Завершение работы дочернего процесса
');
return 0;
}
26.3. Каналы типа FIFO
Канал FIFO — это канал, основанный на принципе очереди: «первым вошел, первым вышел». От обычного канала канал FIFO отличается следующим:
♦ Канал FIFO сохраняется в файловой системе в виде файла, поэтому каналы FIFO называются именованными.
♦ С именованным каналом, как с обычным файлом, могут работать все процессы, а не только предок и потомки.
♦ В отличие от полудуплексного канала, находящегося в ядре, канал FIFO находится в файловой системе и остается там даже после завершения обмена данными. Для следующего использования канала его не нужно заново создавать.
Создать именованный канал можно с помощью командного интерпретатора:
$ mknod myFIFO p
$ mkfifo a=rw myFIFO
или системного вызова mknod():
int mknod(char *pathname, mode_t mode, dev_t dev);
Функция mknod() используется не только для создания каналов FIFO. Она может создать любой i-узел (errno
, которая равна:
♦ EFAULT, ENOTDIR, ENOENT — неправильно задан путь;
♦ EACCESS — у вас недостаточно прав;
♦ ENAMETOOLONG — слишком длинный путь.
Пример создания FIFO-канала:
mknod('FIFO', S_IFIFO|0666, 0);
В текущем каталоге будет создан канал FIFO с правами доступа 0666.
Указывая права доступа создаваемого файла, помните, что они находятся под влиянием umask. Поэтому, если вы хотите установить истинное значение прав доступа, используйте системный вызов umask(0), чтобы временно отключить влияние umask:
umask(0);
mknod('FIFO', S_IFIFO|0666, 0);
Рассмотрим программу, создающую FIFO-канал и ожидающую данных по этому каналу. Программа после создания канала будет ожидать данных по этому каналу и не завершится до тех пор, пока вы не «убьете» процесс.
Листинг 26.3. Процесс-читатель
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/stat.h>
/* Наш канал называется FIFO, он будет создан в текущем
каталоге */
#define FIFO 'FIFO'
void main(void) {
FILE * fp;
/* Буфер для чтения */
char buf[126];
/* Создаем канал, если он еще не создан,