Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


Задача №2 - неименованные программные каналы

Управление процессами в ОС UNIX

 

Цель работы

Ознакомиться со средствами организации взаимодействия процессов в ОС UNIX.

 

Содержание работы

  1. Ознакомиться со средствами организации взаимодействия процессов в ОС UNIX.
  2. Для указанного варианта составить следующие программы на языке Си:
    • реализующую конвейер из двух фильтров (формулировка одного фильтра задана, второй фильтр необходимо придумать);
    • организующую взаимодействие двух процессов через неименованный программный канал;

· организующую взаимодействие двух процессов через именованный программный канал.

Примечание. Проиллюстрировать работу неименованного программного канала и именованного программного канала на макетных программах с применением фильтров, используемых в задаче №1.

3. Защитить лабораторную работу, ответив на контрольные вопросы.

Методические указания к лабораторной работе

 

Таблица 1. Основные системные вызовы, используемые в задачах

  fork() Системный вызов, создающий новый процесс (потомок), который является практически полной копией процесса-родителя, выполняющего этот вызов
  wait(int *status) Ожидание завершения процесса-потомка родительским процессом
  execl() Все формы системного вызова exec превращают вызвавший процесс в новый процесс, который строится из обычного выполняемого файла, называемого в дальнейшем новым выполняемым файлом. Если системный вызов exec закончился успешно, то он не может вернуть управление, так как вызвавший процесс уже заменен новым процессом.
  pipe(p) p – целый массив из двух элементов: int p[2]; Дескриптор файла p[0] используется для представления конца канала, предназначенного для чтения, а дескриптор файла p[1] – для представления конца канала, предназначенного для записи.
  fdopen(<дескриптор_файла> <режим_открытия_файла>) fdopen ассоциирует поток с файловым дескриптором полученным от функции open()
  dup(p[0]) Наименьший доступный дескриптор файла, т.е. 0, и p[0], т.е. конец канала p для чтения, становятся синонимами
  close(0) Дескриптор файла 0 закрывается в связи с закрытием ассоциированного с ним файла, т.е. файла стандартного ввода

 

 

Задача №1 - конвейер из двух фильтров

 

Пример: Программная реализация конвейера ls | wc, подсчитывающего количество программ в текущем каталоге.

void main(void) /* LSWS.C */

/* Создание программного канала */

/* для команд ls и wc */

{

int pid, pid2;

int fd[2];

int status, dead;

switch(pid = fork())

{

case -1: /* Cбой при вызове fork() */

printf("Ошибка при вызове fork() #1 \n");

exit(1);

case 0: /* ПОТОМОК #1 */

pipe(fd);

 

switch(pid2 = fork())

{

case -1: /* Cбой при вызове fork() */

printf("Ошибка при вызове fork() #2 \n");

exit(2);

case 0: /* ПОТОМОК #2 */

close(0); dup(fd[0]); close(fd[0]); close(fd[1]);

execl("/usr/bin/wc", "wc", 0);

puts("Ошибка при вызове WC \n");

exit();

default: /* */

close(1); dup(fd[1]);

close(fd[1]); close(fd[0]);

execl("/bin/ls", "ls", 0);

puts("Ошибка при вызове LS\n");

exit();

default: /* ПРЕДОК ГЛАВНЫЙ */

dead = wait(&status);

exit();

}

}

 

 

Задача №2 - неименованные программные каналы

 

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

 

Пусть входной файл содержит команды форматирования (они начинаются с ‘.’ в первом символе строки) и текст:

.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);

}

 

 



<== предыдущая лекция | следующая лекция ==>
Лр4-с основные виды защиты, используемые в АИТ банковской деятельности | I Механические колебания. Вынужденные колебания. Резонанс
Поделиться с друзьями:


Дата добавления: 2015-11-05; Мы поможем в написании ваших работ!; просмотров: 946 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Сложнее всего начать действовать, все остальное зависит только от упорства. © Амелия Эрхарт
==> читать все изречения...

2160 - | 2048 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.01 с.