Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Processes - Metodicka (edited) with MPI - last....doc
Скачиваний:
61
Добавлен:
22.12.2018
Размер:
1.59 Mб
Скачать
      1. Модель «клиент-сервер».

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

/* процесс-сервер*/

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

#include <unistd.h>

int main(int argc, char **argv)

{

int fd;

int pid;

mkfifo("fifo", S_IFIFO | 0666);

/*создали специальный файл FIFO с открытыми для всех правами доступа на чтение и запись*/

fd = open("fifo", O_RDONLY | O_NONBLOCK);

/* открыли канал на чтение*/

while (read (fd, &pid, sizeof(int)) == -1) ;

printf("Server %d got message from %d !\n", getpid(), pid);

close(fd);

unlink("fifo");/*уничтожили именованный канал*/

return 0;

}

/* процесс-клиент*/

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

#include <fcntl.h>

int main(int argc, char **argv)

{

int fd;

int pid = getpid( );

fd = open("fifo", O_RDWR);

write(fd, &pid, sizeof(int));

close(fd);

return 0;

}

    1. Нелокальные переходы.

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

Как известно, оператор goto позволяет осуществлять безусловный переход только внутри одной функции. Это ограничение связано с необходимостью сохранения целостности стека: в момент входа в функцию в стеке отводится место, называемое стековым кадром, где записываются адрес возврата, фактические параметры, отводится место под автоматические переменные. Стековый кадр освобождается при выходе из функции. Соответственно, если при выполнении безусловного перехода процесс минует тот фрагмент кода, где происходит освобождение стекового кадра, и управление непосредственно перейдет в другую часть программы (например, в объемлющую функцию), то фактическое состояние стека не будет соответствовать текущему участку кода, и тем самым стек подвергнется разрушению.

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

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

#include <setjmp.h>

int setjmp(jmp_buf env);

void longjmp(jmp_buf env, int val);

Вызов setjmp() используется для регистрации некоторой точки кода, которая в дальнейшем будет использоваться в качестве пункта назначения для нелокального перехода, а вызов longjmp() – для перехода в одну из ранее зарегистрированных конечных точек.

При обращении к вызову setjmp(), происходит сохранение параметров текущей точки кода (значения счетчика адреса, позиции стека, регистров процессора и реакций на сигналы). Все эти значения сохраняются в структуре типа jmp_buf, которая передается вызову setjmp() в качестве параметра. При этом вызов setjmp() возвращает 0.

После того, как нужная точка кода зарегистрирована с помощью вызова setjmp(), управление в нее может быть передано при помощи вызова longjmp(). При этом в качестве первого параметра ему указывается та структура, в которой были зафиксированы атрибуты нужной нам точки назначения. После осуществления вызова longjmp() процесс продолжит выполнение с зафиксированной точки кода, т.е. с того места, где происходит возврат из функции setjmp(), но в отличие от первого обращения к setjmp(), возвращающим значением setjmp() станет не 0, а значение параметра val в вызове longjmp(), который произвел переход.

Отметим, что если программист желает определить в программе несколько точек назначения для нелокальных переходов, каждая из них должна быть зарегистрирована в своей структуре типа jmp_buf. С другой стороны, разумеется, на одну и ту же точку назначения можно переходить из разных мест программы, при этом, чтобы различить, из какой точки был произведен нелокальный переход, следует указывать при переходах разные значения параметра val. В любом случае, при вызове longjmp() значение параметра val не должно быть нулевым (даже если оно есть 0, то возвращаемое значение setjmp() будет установлено в 1). Кроме того, переход должен производиться только на такие точки, которые находятся в коде одной из вызывающих функций для той функции, откуда осуществляется переход (в том числе, переход может быть произведен из функции-обработчика сигнала). При этом в момент перехода все содержимое стека, используемое текущей функцией и всеми вызывающими, вплоть до необходимой, освобождается.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]