Реферат: Управление процессами
Программные каналы. Сначала несколько слов о концепции. Есть два процесса, и мы хотим организовать взаимодействие между этими процессами путем передачи данных от одного процесса к другому. В системе UNIX для этой цели используются т.н. каналы. С точки зрения программы, канал есть некая сущность, обладающая двумя файловыми дескрипторами. Через один ФД процесс может писать информацию в канал, через другой ФД процесс может читать информацию из канала. Так как канал это нечто, связанное с файловыми дескрипторами, то канал может передаваться по наследству сыновним процессам. Это означает, что два родственных процесса могут обладать одним и тем же каналом. Это означает, что если один процесс запишет какую-то информацию в канал, то другой процесс может прочесть эту информацию из этого же канала.
Особенности работы с каналом. Под хранение информации, передаваемой через канал, выделяется некоторый фиксированный объем оперативной памяти. В некоторых системах этот буфер может быть продолжен на внешнюю память. Что происходит, если процесс хочет записать информацию в канал, а буфер переполнен, или прочесть информацию из канала, а в буфере нет еще данных? В обоих случаях процесс приостанавливает свое выполнение и дожидается, пока не освободится место либо, соответственно, пока в канале не появится информация. Надо заметить, что в этих случаях работа процесса может изменяться в зависимости от установленных параметров, которые можно менять программно (и реакцией на эти ситуации может быть не ожидание, а возврат некоторого кода ответа).
Давайте посмотрим, как эти концепции реализуются в системе. Есть функция pipe . Аргументом этой функции должен быть указатель на массив двух целых переменных.
int pipe(pipes);
int pipes[2];
Нулевой элемент массива после обращения к функции pipe получаетФД для чтения, первый элемент этого массива получает ФД для записи. Если нет свободных ФД, то эта функция возвращает -1. Признак конца файла для считывающего дескриптора не будет получен до тех пор, пока не закрыты все дескрипторы, связанные с записью в этот канал. Рассмотрим небольшой пример:
char *s = “ Это пример ”;
char b[80];
int pipes[2];
pipe(pipes);
write(pipes[1],s, strlen(s)+1);
read(pipes[0],s, strlen(s)+1);
Это пример копирования строки (понятно, что так копировать строки не надо, и вообще никто функцией pipe в пределах одного процессане пользуется). В этом примереи в последующих не обрабатываются случаи отказа. Теперь давайте рассмотрим более содержательный пример. Напишем пример программы, которая запустит и свяжет каналом два процесса:
main()
{
int fd[2];
pipe(fd); /* в отцовском процессе образуем два дескриптора канала */
if (fork()) /* образуем процесс-сын, у которого будут те же дескрипторы */
{ /* эта часть программы происходит в процессе-отце */
dup2(fd[1],1); /* заменяем стандартный вывод выводом в канал */
close(fd[1]); /* закрываем дескрипторы канала */
close(fd[0]); /* теперь весь вывод итак будет происходить в канал */
execl(“/bin/ls”,“ls”,(char*)0); /* заменяем тело отца на ls*/
} /* отсюда начинает работать процесс-сын */
dup2(fd[0],0); /* в процессе сыне все делаем аналогично */
close(fd[0]);
close(fd[1]);
execl(“/bin/wc”,“wc”,(char*)0);
}