Операционная система UNIX - страница 111
) (если процесс не установил обработки сигнала >SIGPIPE
, производится обработка по умолчанию — процесс завершается).
В качестве примера приведем простейший пример приложения клиент- сервер, использующего FIFO для обмена данными. Следуя традиции, клиент посылает серверу сообщение "Здравствуй, Мир!", а сервер выводит это сообщение на терминал.
>#include
>#include
>#define FIFO "fifo.1"
>#define MAXBUFF 80
>main() {
> int readfd, n;
> char buff[MAXBUFF]; /* буфер для чтения данных из FIFO */
> /* Создадим специальный файл FIFO с открытыми для всех
> правами доступа на чтение и запись */
> if (mknod(FIFO, S_IFIFO | 0666, 0) < 0) {
> printf("Невозможно создать FIFO\n");
> exit(1);
> }
> /* Получим доступ к FIFO */
> if ((readfd = open(FIFO, O_RDONLY)) < 0) {
> printf("Невозможно открыть FIFO\n");
> exit(1);
> }
> /* Прочитаем сообщение ("Здравствуй, Мир!") и выведем его
> на экран */
> while ((n = read(readfd, buff, MAXBUFF)) > 0)
> if {write(1, buff, n) != n) {
> printf("Ошибка вывода\n");
> exit(1);
> }
> /* Закроем FIFO, удаление FIFO - дело клиента */
> close(readfd);
> exit(0);
>}
>#include
>#include
>/* Соглашение об имени FIFO */
>#define FIFO "fifo.1"
>main() {
> int writefd, n;
> /* Получим доступ к FIFO */
> if ((writefd = open(FIFO, O_WRONLY)) < 0) {
> printf("Невозможно открыть FIFO\n");
> exit(1);
> }
> /* Передадим сообщение серверу FIFO */
> if (write(writefd, "Здравствуй, Мир!\n", 18) != 18) {
> printf("Ошибка записи\n");
> exit(1);
> }
> /* Закроем FIFO */
> close(writefd);
> /* Удалим FIFO */
> if (unlink(FIFO) < 0) {
> printf("Невозможно удалить FIFO\n");
> exit(1);
> }
> exit(0);
>}
Идентификаторы и имена в IPC
Как было показано, отсутствие имен у каналов делает их недоступными для независимых процессов. Этот недостаток устранен у FIFO, которые имеют имена. Другие средства межпроцессного взаимодействия, являющиеся более сложными, требуют дополнительных соглашений по именам и идентификаторам. Множество возможных имен объектов конкретного типа межпроцессного взаимодействия называется пространством имен (name space). Имена являются важным компонентом системы межпроцессного взаимодействия для всех объектов, кроме каналов, поскольку позволяют различным процессам получить доступ к общему объекту. Так, именем FIFO является имя файла именованного канала. Используя условленное имя созданного FIFO два процесса могут обращаться к этому объекту для обмена данными.
Для таких объектов IPC, как очереди сообщений, семафоры и разделяемая память, процесс назначения имени является более сложным, чем просто указание имени файла. Имя для этих объектов называется ключом (key) и генерируется функцией ftok(3C) из двух компонентов — имени файла и идентификатора проекта:
>#include
>#include
>key_t ftok(char* filename, char proj);
В качестве >filename
можно использовать имя некоторого файла, известное взаимодействующим процессам. Например, это может быть имя программы-сервера. Важно, чтобы этот файл существовал на момент создания ключа. Также нежелательно использовать имя файла, который создается и удаляется в процессе работы распределенного приложения, поскольку при генерации ключа используется номер inode файла. Вновь созданный файл может иметь другой inode и впоследствии процесс, желающий иметь доступ к объекту, получит неверный ключ.
Пространство имен позволяет создавать и совместно использовать IPC неродственным процессам. Однако для ссылок на уже созданные объекты используются идентификаторы, точно так же, как файловый дескриптор используется для работы с файлом, открытым по имени.
Каждое из перечисленных IPC имеет свой уникальный дескриптор (идентификатор), используемый ОС (ядром) для работы с объектом. Уникальность дескриптора обеспечивается уникальностью дескриптора для каждого из типов объектов (очереди сообщений, семафоры и разделяемая память), т.е. какая-либо очередь сообщений может иметь тот же численный идентификатор, что и разделяемая область памяти (хотя любые две очереди сообщений должны иметь различные идентификаторы).
Таблица 3.5