Продолжая использовать наш сайт, вы даете согласие на обработку файлов cookie, которые обеспечивают правильную работу сайта. Благодаря им мы улучшаем сайт!
Принять и закрыть

Читать, слущать книги онлайн бесплатно!

Электронная Литература.

Бесплатная онлайн библиотека.

Читать: UNIX: взаимодействие процессов - Уильям Ричард Стивенс на бесплатной онлайн библиотеке Э-Лит


Помоги проекту - поделись книгой:

set shmsys:shminfo_shmmax = значение

set shmsys:shminfo_shmmni = значение

Последние шесть символов имени слева от знака равенства представляют собой переменные, перечисленные в табл. 6.2, 11.1 и 14.1.

В Digital Unix 4.0B программа sysconfig позволяет узнать или изменить множество параметров и ограничений ядра. Ниже приведен вывод этой команды, запущенной с параметром –q. Команда выводит текущие ограничения для подсистемы ipc. Некоторые строки в выводе, не имеющие отношения к средствам IPC System V, были опущены:

alpha % /sbin/sysconfig –q ipc

ipc:

msg-max = 8192

msg-mnb = 16384

msg-mni = 64

msg-tql = 40

shm-max = 4194304

shm-min = 1

shm-mni = 128

shm-seg = 32

sem-mni = 16

sem-msl = 25

sem-opm = 10

sem-ume = 10

sem-vmx = 32767

sem-aem = 16384

num-of-sems = 60

Для этих параметров можно указать другие значения по умолчанию, изменив файл /etc/sysconfigtab. Делать это следует с помощью программы sysconfigdb. Этот файл также считывается в процессе начальной загрузки системы.

3.9. Резюме

Первым аргументом функций msgget, semget и shmget является ключ IPC System V. Эти ключи вычисляются по полному имени файла с помощью системной функции ftok. В качестве ключа можно также указать значение IPCPRIVATE. Эти три функции создают новый объект IPC или открывают существующий и возвращают идентификатор System V IPC — целое число, которое потом используется для распознавания объекта в прочих функциях, имеющих отношение к IPC. Эти идентификаторы имеют смысл не только в рамках одного процесса (как дескрипторы файлов), но и в рамках всей системы. Они могут повторно использоваться ядром, но лишь спустя некоторое время.

С каждым объектом System V IPC связана структура ipc_perm, содержащая информацию о нем, такую как идентификатор пользователя владельца, идентификатор группы, разрешения чтения и записи и др. Одним из отличий между System V и Posix IPC является то, что для объекта IPC System V эта информация доступна всегда (доступ к ней можно получить с помощью одной из функций XXXctl с аргументом IPC_STAT), а в Posix IPC доступ к ней зависит от реализации. Если объект Posix IPC хранится в файловой системе и мы знаем его имя в ней, мы можем получить доступ к этой информации, используя стандартные средства файловой системы.

При создании нового или открытии существующего объекта System V IPC функции getXXX передаются два флага (IPC_CREAT и IPC_EXCL) и 9 бит разрешений.

Без сомнения, главнейшей проблемой в использовании System V IPC является наличие искусственных ограничений в большинстве реализаций. Ограничения накладываются на размер объектов, причем они берут свое начало от самых первых реализаций. Это означает, что для интенсивного использования средств System V IPC приложениями требуется изменение ограничений ядра, а внесение этих изменений в каждой системе осуществляется по-разному. 

Упражнения

1. Прочитайте о функции msgctl в разделе 6.5 и измените программу в листинге 3.2 так, чтобы выводился не только идентификатор, но и поле seq структуры ipc_perm.

2. Непосредственно после выполнения программы листинга 3.2 мы запускаем программу, создающую две очереди сообщений. Предполагая, что никакие другие приложения не использовали очереди сообщений с момента загрузки системы, определите, какие значения будут возвращены функцией msgget в качестве идентификаторов очередей сообщений.

3. В разделе 3.5 было отмечено, что функции getXXX System V IPC не используют маску создания файла. Напишите тестовую программу, создающую канал FIFO (с помощью функции mkfifо, описанной в разделе 4.6) и очередь сообщений System V, указав для обоих разрешение 666 (в восьмеричном формате). Сравните разрешения для созданных объектов (FIFO и очереди сообщений). Перед запуском программы удостоверьтесь, что значение umask отлично от нуля.

4. Серверу нужно создать уникальную очередь сообщений для своих клиентов. Что предпочтительнее: использовать какое-либо постоянное имя файла (например, имя сервера) в качестве аргумента функции ftok или использовать ключ IPC_PRIVATE?

5. Измените листинг 3.1 так, чтобы выводился только ключ IPC и путь к файлу. Запустите программу find, чтобы вывести список всех файлов вашей файловой системы, и передайте вывод вашей только что созданной программе. Скольким именам файлов будет соответствовать один и тот же ключ?

6. Если в вашей системе есть программа sar (system activity reporter — информация об активности системы), запустите команду

sar –m 5 6

На экран будет выведено количество операций в секунду с очередями сообщений и семафорами, замеряемыми каждые 5 секунд 6 раз. 

ЧАСТЬ 2

ОБМЕН СООБЩЕНИЯМИ

ГЛАВА 4

Именованные и неименованные каналы

4.1. Введение

Неименованные каналы — это самая первая форма IPC в Unix, появившаяся еще в 1973 году в третьей версии (Third Edition [17]). Несмотря на полезность во многих случаях, главным недостатком неименованных каналов является отсутствие имени, вследствие чего они могут использоваться для взаимодействия только родственными процессами. Это было исправлено в Unix System III (1982) добавлением каналов FIFO, которые иногда называются именованными каналами. Доступ и к именованным каналам, и к неименованным организуется с помощью обычных функций read и write.

ПРИМЕЧАНИЕ

Программные (неименованные) каналы в принципе могут использоваться неродственными процессами, если предоставить им возможность передавать друг другу дескрипторы (см. раздел 15.8 этой книги или раздел 13.7 [24]). Однако на практике эти каналы обычно используются для осуществления взаимодействия между процессами, у которых есть общий предок.

В этой главе описываются детали, касающиеся создания и использования программных каналов и каналов FIFO. Мы рассмотрим пример простейшего сервера файлов, а также обратим внимание на некоторые детали модели клиент-сервер, в частности постараемся определить количество требуемых каналов IPC, сравним последовательные серверы с параллельными и неструктурированные потоки байтов с сообщениями.

4.2. Приложение типа клиент-сервер

Пример приложения модели клиент-сервер приведен на рис. 4.1. Именно на него мы будем ссылаться в тексте этой главы и главы 6 при необходимости проиллюстрировать использование программных каналов, FIFO и очередей сообщений System V.

Клиент считывает полное имя (файла) из стандартного потока ввода и записывает его в канал IPC. Сервер считывает это имя из канала IPC и производит попытку открытия файла на чтение. Если попытка оказывается успешной, сервер считывает файл и записывает его в канал IPC. В противном случае сервер возвращает клиенту сообщение об ошибке. Клиент считывает данные из канала IPC и записывает их в стандартный поток вывода. Если сервер не может считать файл, из канала будет считано сообщение об ошибке. В противном случае будет принято содержимое файла. Две штриховые линии между клиентом и сервером на рис. 4.1 представляют собой канал IPC. 

Рис. 4.1. Пример приложения типа клиент-сервер

4.3. Программные каналы

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

#include <unistd.h>

int pipe(int fd[2]);

/* возвращает 0 в случае успешного завершения. –1 – в случае ошибки:*/

Функция возвращает два файловых дескриптора: fd[0] и fd[1], причем первый открыт для чтения, а второй — для записи.

ПРИМЕЧАНИЕ

Некоторые версии Unix, в частности SVR4, поддерживают двусторонние каналы (full-duplex pipes). В этом случае канал открыт на запись и чтение с обоих концов. Другой способ создания двустороннего канала IPC заключается в вызове функции socketpair, описанной в разделе 14.3 [24]. Его можно использовать в большинстве современных версий Unix. Однако чаще всего каналы используются при работе с интерпретатором команд, где уместно использование именно односторонних каналов.

Стандарты Posix.1 и Unix 98 требуют только односторонних каналов, и мы будем исходить из этого.

Для определения типа дескриптора (файла, программного канала или FIFO) можно использовать макрос S_ISFIFO. Он принимает единственный аргумент: поле st_mode структуры stat и возвращает значение «истина» (ненулевое значение) или «ложь» (ноль). Структуру stat для канала возвращает функция fstat. Для FIFO структура возвращается функциями fstat, lstat и stat.

На рис. 4.2 изображен канал при использовании его единственным процессом.

Рис. 4.2. Канал в одиночном процессе

Хотя канал создается одним процессом, он редко используется только этим процессом (пример канала в одиночном процессе приведен в листинге 5.12). Каналы обычно используются для связи между двумя процессами (родительским и дочерним) следующим образом: процесс создает канал, а затем вызывает fork, создавая свою копию — дочерний процесс (рис. 4.3). Затем родительский процесс закрывает открытый для чтения конец канала, а дочерний, в свою очередь, — открытый на запись конец канала. Это обеспечивает одностороннюю передачу данных между процессами, как показано на рис. 4.4.

Рис. 4.3. Канал после вызова fork

Рис. 4.4. Канал между двумя процессами 

При вводе команды наподобие

who|sort|lp

в интерпретаторе команд Unix интерпретатор выполняет вышеописанные действия для создания трех процессов с двумя каналами между ними. Интерпретатор также подключает открытый для чтения конец каждого канала к стандартному потоку ввода, а открытый на запись — к стандартному потоку вывода. Созданный таким образом канал изображен на рис. 4.5.

Рис. 4.5. Каналы между тремя процессами при конвейерной обработке 

Все рассмотренные выше каналы были однонаправленными (односторонними), то есть позволяли передавать данные только в одну сторону. При необходимости передачи данных в обе стороны нужно создавать пару каналов и использовать каждый из них для передачи данных в одну сторону. Этапы создания двунаправленного канала IPC следующие:

1. Создаются каналы 1 (fd1[0] и fd1[1]) и 2 (fd2[0] и fd2[1]).

2. Вызов fork.

3. Родительский процесс закрывает доступный для чтения конец канала 1 (fd1[0]).

4. Родительский процесс закрывает доступный для записи конец канала 2 (fd2[1]).

5. Дочерний процесс закрывает доступный для записи конец канала 1 (fd1[1]).

6. Дочерний процесс закрывает доступный для чтения конец канала 2 (fd2[0]).

Текст программы, выполняющей эти действия, приведен в листинге 4.1. При этом создается структура каналов, изображенная на рис. 4.6.

Рис. 4.6. Двусторонняя передача данных по двум каналам

Пример

Давайте напишем программу, описанную в разделе 4.2, с использованием каналов. Функция main создает два канала и вызывает fork для создания копии процесса. Родительский процесс становится клиентом, а дочерний — сервером. Первый канал используется для передачи полного имени от клиента серверу, а второй — для передачи содержимого файла (или сообщения об ошибке) от сервера клиенту. Таким образом мы получаем структуру, изображенную на рис. 4.7. 

Рис. 4.7. Реализация рис. 4.1 с использованием двух каналов

Обратите внимание на то, что мы изображаем на рис. 4.7 два канала, соединяющих сервер с клиентом, но оба канала проходят через ядро, поэтому каждый передаваемый байт пересекает интерфейс ядра дважды: при записи в канал и при считывании из него.

В листинге 4.1[1] приведена функция main для данного примера.

Листинг 4.1. Функция main для приложения клиент-сервер, использующего два канала

//pipe/mainpipe.c

1  #include "unpipc.h"

2  void client(int, int), server(int, int);

3  int

4  main(int argc, char **argv)

5  {

6   int pipe1[2], pipe2[2]:

7   pid_t childpid;

8   Pipe(pipe1); /* создание двух каналов */

9   Pipe(pipe2);

10  if ((childpid = Fork()) == 0) { /* child */

11   Close(pipe1[1]);

12   Close(pipe2[0]);

13   server(pipe1[0], pipe2[1]);

14   exit(0);

15  }



Поделиться книгой:

На главную
Назад