русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Неименованные каналы (PIPE)


Дата добавления: 2014-11-27; просмотров: 2541; Нарушение авторских прав


Канал — поток данных между двумя или несколькими процессами, имеющий интерфейс, аналогичный чтению или записи в файл.

Неименованный канал является средством взаимодействия между связанными процессами - родительским и дочерним. Родительский процесс создает канал при помощи системного вызова:

int pipe(int fd[2]);

 

возвращаются два файловых дескриптора: fd[0] является дескриптором для чтения из канала, fd[1] - дескриптором для записи в канал.

Процесс - источник записывает данные в канал, а процесс - приемник считывает данные, освобождая его для дальнейшего использования.

 

Если родительский процесс, создавший канал, порождает несколько дочерних процессов, то все дочерние процессы подключены к другому концу канала. Если, например, родительский процесс выводит данные в канал, то они "достанутся" тому дочернему процессу, который раньше выполнит системный вызов read.

Канал создаётся по запросу и существует только в ходе работы двух процессов, другие процессы в системе не могут обратиться к этому каналу.

 

- Если нужен двунаправленный обмен данными между процессами, то родительский процесс создает два канала, один из которых используется для передачи данных в одну сторону, а другой - в другую. После получения процессами дескрипторов канала для работы с каналом используются файловые системные вызовы:

int read(int pipe_fd, void *area, int cnt);

int write(int pipe_fd, void *area, int cnt);

 

Первый аргумент этих вызовов - дескриптор канала, второй - указатель на область памяти, с которой происходит обмен, третий - количество байт. Оба вызова возвращают число переданных байт (или -1 - при ошибке).

 

Выполнение этих системных вызовов может переводить процесс в состояние ожидания. Это происходит, если процесс пытается читать данные из пустого канала или писать данные в переполненный канал. Процесс выходит из ожидания, когда в канале появляются данные или когда в канале появляется свободное место, соответственно.



 

- popen, pclose - создание и ликвидация канала между программой и командой

 

#include <stdio.h>

 

1- FILE *popen (command, type)

char *command, *type;

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

 

 

Например: FILE *ptr;

ptr = popen (cmd, "r") или f = popen(argv[1], "r");

В параметре argv[1] функции popen передается не имя файла, а команда на запуск программы или команды оболочки, например, "ls -al". Если вызов popen() был успешен, мы можем считывать данные, выводимые запущенной командой, с помощью обычной функции fread(3): fread(buf, 1, BUF_SIZE, f)

Особенность функции popen() заключается в том, что эта функция не возвращает NULL, даже если переданная ей команда не является корректной. Самый простой способ обнаружить ошибку в этой ситуации - попытаться прочесть данные из потока вывода. Если в потоке вывода нет данных (fread() возвращает значение 0), значит произошла ошибка. Для вывода данных, прочитанных с помощью fread(), на терминал мы используем функцию write() с указанием дескриптора стандартного потока вывода: write(1, buf, len);

 

Аргументами функции popen являются указатели на цепочки символов с завершающим нулевым байтом. Первая из них, command, содержит команду shell'а, а вторая задает режим ввода/вывода: "r" для чтения и "w" для записи. Функция popen создает канал между вызывающей программой и указанной командой. Возвращаемое значение - это указатель на поток. Если режим равен "w", то можно писать на стандартный ввод команды, выводя в созданный поток. Если режим равен "r", то можно читать со стандартного вывода команды, вводя из созданного потока.

2- int pclose (stream)

FILE *stream;

 

pclose(f);

 

 

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

 

Поскольку открытые файлы разделяются, команда с режимом "r" может быть использована как входной фильтр, а команда с режимом "w" - как выходной фильтр.

 

- При завершении использования канала процесс выполняет системный вызов:

int close(int pipe_fd);

Если процесс на одной из сторон канала завершается и закрывает канал, другому процессу посылается специальный сигнал — SIGPIPE.

 

 

 

Неименованные каналы поддерживаются командной оболочкой, обеспечивая передачу информации из одной программы (на стандартное устройство - терминал) в другую (прием информации со стандартного устройства - клавиатуры), это достигается с помощью символа "|" при написании команды: $ ps- sf | grep my_proc.

 

Пример: Программа запускает другую программу и считывает данные, которые та выводит в свой стандартный поток вывода. Для решения этой задачи мы воспользуемся функциями popen(3) и pclose(3). Программа makelog выполняет команду оболочки, переданную ей в качестве параметра и записывает данные, выводимые этой командой, одновременно на стандартный терминал и в файл log.txt.

#include <stdio.h>

#include <errno.h>

#define BUF_SIZE 0x100

int main(int argc, char * argv[])

{

FILE * f;

FILE * o;

int len;

char buf[BUF_SIZE];

if (argc != 1) //или 2? – проверка на число аргументов

{ printf("использование: makelog \"<command>\"\n");

return -1;

}

f = popen(argv[1], "r"); //выполнение команды-параметра

if (f == NULL)

{

perror("ошибка:\n");

return -1;

}

o = fopen("log.txt", "w");

while ((len = fread(buf, 1, BUF_SIZE, f)) != 0)

{ write(1, buf, len); //вывод на экран

fwrite(buf, 1, len, o); //вывод в файл

}

pclose(f);

fclose(o);

return 0;
}

Например, если скомпилировать программу:

gcc makelog.c -o makelog

а затем скомандовать

makelog "ls -al"

На экране терминала будут распечатаны данные, выводимые командой оболочки ls -al, а в рабочей директории программы makelog будет создан файл log.txt, содержащий те же данные.

Основным недостатком неименованных каналов является невозможность их использования между процессами, не имеющими общего родителя, но этот недостаток был устранен с появлением именованных каналов (named pipes), или каналов FIFO.

 



<== предыдущая лекция | следующая лекция ==>
Сигналы | Именованные каналы (FIFO)


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.423 сек.