Этот фрагмент кода в особых комментариях не нуждается. Сначала мы создаем поток для чтения (доступ «r») информации от порожденного процесса (ls *.txt). Затем в цикле while читаем имена файлов до тех пор, пока не будет достигнут конец файла. После окончания операции ввода/вывода закрываем поток вызовом pclose(fp)
.Вот теперь мы готовы к тому, чтобы рассмотреть более серьезный пример. В этом примере мы будем передавать данные дочернему процессу. Задача такова: у нас есть две программы. Первая программа передает второй какую-нибудь информацию, вторая обрабатывает ее и выводит на стандартный вывод результат.
Листинг 26.1. Родительский процесс
#include
#include
#include
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 могу открыть канал.\n");
exit(1);
}
printf("Введите информацию для передачи дочернему процессу ");
// читаем ввод пользователя
fgets(buff, sizeof(buff), stdin);
// передаем данные дочернему процессу
fprintf(cp, "%s\n", buff);
// "выталкиваем" содержимое буфера в канал
fflush(cp);
// закрываем канал и проверяем состояние вызова pclose()
status=pclose(cp);
if (!WIFEXITED(status))
printf("ошибка при закрытии канала\n");
printf("Завершение работы родительского процесса\n");
return 0;
}
Листинг 26.2. Дочерний процесс — исходный код /usr/bin/child
#include
int main() {
char buff[1024]={0};
fgets(buff, sizeof(buff), stdin);
printf("Прочитал со стандартного ввода: %s\n", buff);
printf("Завершение работы дочернего процесса\n");
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
#include
#include
#include
#include
/* Наш канал называется FIFO, он будет создан в текущем
каталоге */
#define FIFO "FIFO"
void main(void) {
FILE * fp;
/* Буфер для чтения */