Этот фрагмент кода в особых комментариях не нуждается. Сначала мы создаем поток для чтения (доступ «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;
}
Канал 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;
/* Буфер для чтения */
Вильям Л Саймон , Вильям Саймон , Наталья Владимировна Макеева , Нора Робертс , Юрий Викторович Щербатых
Зарубежная компьютерная, околокомпьютерная литература / ОС и Сети, интернет / Короткие любовные романы / Психология / Прочая справочная литература / Образование и наука / Книги по IT / Словари и Энциклопедии