Пример: взаимодействие родственных процессов в дуплексном режиме (используются два программных канала) и переназначение стандартного ввода-вывода.
Пусть входной файл содержит команды форматирования (они начинаются с ‘.’ в первом символе строки) и текст:
.R
aaaaaaa
.B
ccccccc
...
Для решения задачи используем 2 параллельных процесса:
· textcount – читает текстовый файл и при передаче строк процессу count удаляет из них команды форматирования;
· count – подсчитывает получаемые от процесса textcount символы и по достижении конца текста посылает общее число знаков первому процессу.
Порождающий и порожденный процессы должны взаимодействовать, используя два канала p и q.
Рис. 1. Взаимодействие родственных процессов в дуплексном режиме
Порожденный процесс выполняет независимо написанную программу (Count), которая читает данные из входного потока stdin (точка 1) и записывает их в стандартный выходной поток stdout (точка 2), т.е. использует функции getchar() и printf().
#include <stdio.h>
#define R 0 /* stdin */
|
|
#define W 1 /* stdout */
#define True 1
#define FALSE 0
#define PERIOD '.'
void main(void) /* Textcount.c */
{
int pid;
int p[2], q[2];
FILE *fdopen(), *fp;
int c;
int newline = TRUE;
int total;
/* Установка программных каналов p и q */
pipe(p);
pipe(q);
/* p[R], q[R] - концы каналов для чтения */
/* p[W], q[W] - концы каналов для записи */
switch(pid = fork())
{
case 0: /* ПОТОМОК */
/* читает из p[R] */
/* пишет в q[W] */
/* p[W] и q[R] - закрыты */
/* станд. ввод и p[R] - синонимы */
/* станд. вывод и q[W] синонимы */
/* Канал P */
close(p[W]);
close(R); dup(p[R]); close(p[R]);
/* Теперь станд. ввод и p[R] - синонимы */
/* Канал Q */
close(q[R]);
close(W); dup(q[W]); close(q[W]);
/* Теперь станд. вывод и q[W] - синонимы */
/* Запуск внешней независимой программы Count */
execl("count", "count", 0);
printf("textcount: Ошибка при вызове");
exit(1);
case -1: /* Cбой при вызове fork() */
printf("Ошибка при вызове fork() \n");
exit(1);
default: /* Это ПРЕДОК */
/* Конец канала P преобразуется для */
/* записи в поток */
close(p[R]); close(q[W]);
fp = fdopen(p[W], "w");
/* Посылка текстового файла в процесс COUNT */ while((c=getchar()!= EOF)
{
switch(newline)
{
case TRUE:
if (c == '\n') /* Пустая строка */
putc(c, fp);
else if (c == PERIOD)
/* Пропустить строку */
while((c=getchar()!= EOF && c!= '\n');
else
{
putc(c, fp);
newline = FALSE;
}
break;
default:
putc(c, fp);
if (c == '\n')
newline = TRUE;
}
}
fclose(fp); /* Чтобы принимающий процесс мог воспринимать */
/* EOF на конце канала для чтения */
/* Теперь подключаем ввод результата */
/* из канала Q */
close(R); dup(q[R]); close(q[R]);
scanf("%d", &total);
printf("Общее число знаков %d\n", total);
exit(0);
}
}
/* Независимая программа Count – подсчет символов, полученных от процесса Textcount */
void main(void) /* COUNT.C */
/* Процесс, выполняющий COUNT, должен */
/* переназначить ввод и вывод так, */
/* чтобы ввод данных выполнялся из канала P, */
/* а вывод - канал Q */
/* */
{
int count = 0;
while (getchar()!= EOF)
count++; printf("%d\n", count);
}