Выбрать главу

Первый аргумент функции popen() является командой интерпретатора, выполняемой в подпроцессе /bin/sh. Интерпретатор просматривает переменную среды PATH, чтобы определить, где следует искать команду. Если второй аргумент равен "r", функция возвращает указатель на стандартный выходной поток дочернего процесса, чтобы программа могла читать данные из него. Если второй аргумент равен "w", функция возвращает указатель на стандартный входной поток дочернего процесса, чтобы программа могла записывать данные в него. В случае ошибки возвращается пустой указатель.

Функция pclose() закрывает поток, указатель на который был возвращен функцией popen(), и дожидается завершения дочернего процесса.

5.4.5. Каналы FIFO

Файл 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

Первый символ в строке режима (p) указывает на то, что файл имеет тип FIFO (именованный канал). Теперь в одном терминальном окне можно осуществлять чтение из файла с помощью команды

% cat < /tmp/fifo

а в другом окне можно выполнять запись в файл:

% cat > /tmp/fifo

Попробуйте во втором окне ввести какой-то текст и нажать <Enter>. Введенный текст немедленно отобразится в первом окне. Канал закрывается нажатием клавиш <Ctrl+D> во втором окне. FIFO-файл удаляется с помощью следующей команды:

% rm /tmp/fifo

Создание FIFO-файла

FIFO-файл можно создать программным путем с помощью функции mkfifo(). Первым аргументом является путь к файлу. Второй аргумент задает права доступа к каналу со стороны его владельца, группы и остальных пользователей (об этом пойдет речь в разделе 10.3, "Права доступа к файлам"). Поскольку у канала есть читающая и записывающая стороны, права доступа должны учитывать оба случая. Если канал не может быть создан (например, файл с таким именем уже существует), функция mkfifo() возвращает -1. Для работы функции требуется подключить к программе файлы <sys/types.h> и <sys/stat.h>.

Доступ к FIFO-файлу

К FIFO-файлу можно обращаться как к обычному файлу. При организации межзадачного взаимодействия одна программа должна открыть файл для записи, а другая - для чтения. Над файлом можно выполнять как низкоуровневые (open(), write(), read(), close() и др.), так и высокоуровневые (fopen(), fprintf(), fscanf(), fclose() и др.) функции.

Например, на низком уровне запись блока данных в FIFO-файл осуществляется следующим образом:

int fd = open(fifo_path, O_WRONLY);

write(fd, data, data_length);

close(fd);

А так выполняется чтение строки из FIFO-файла на высоком уровне:

FILE* fifo = fopen(fifo_path, "r");

fscanf(fifo, "%s", buffer);

fclose(fifo);

У FIFO-файла одновременно может быть несколько читающих и записывающих программ. Входные потоки разбиваются на атомарные блоки, размер которых определяется константой PIPE_BUF (4 Кбайт в Linux). Если несколько программ параллельно друг другу осуществляют запись в файл, их блоки будут чередоваться. То же самое относится к программам. одновременно читающим данные из файла.

Отличия от именованных каналов в Windows

Каналы операционных систем семейства Win32 очень напоминают каналы Linux. Основное различие касается именованных каналов, которые в Win32 функционируют скорее как сокеты. Именованные каналы Win32 способны соединять по сети процессы, выполняющиеся на разных компьютерах. В Linux для этой цели используются именно сокеты. Кроме того, в Win32 допускается, чтобы несколько программ чтения или записи работали с именованным каналом, не перекрывая потоки друг друга, а сами каналы поддерживают двунаправленный обмен данными.[17]

вернуться

17

Именованный канал можно создать только в Windows NT. В Windows 9х программы могут устанавливать только клиентские соединения.