на главную | войти | регистрация | DMCA | контакты | справка | donate |      

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Э Ю Я


моя полка | жанры | рекомендуем | рейтинг книг | рейтинг авторов | впечатления | новое | форум | сборники | читалки | авторам | добавить



12.1. Введение

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

ПРИМЕЧАНИЕ

Говоря «не требуется участие ядра», мы подразумеваем, что процессы не делают системных вызовов для передачи данных. Очевидно, что все равно именно ядро обеспечивает отображение памяти, позволяющее процессам совместно ею пользоваться, и затем обслуживает эту память (обрабатывает сбои страниц и т. п.).

Рассмотрим по шагам работу программы копирования файла типа клиент-сервер, которую мы использовали в качестве примера для иллюстрации различных способов передачи сообщений (рис. 4.1).

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

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

ПРИМЕЧАНИЕ

Мы говорим «обычно», поскольку очереди сообщений Posix могут быть реализованы через отображение файла в память (функцию mmap мы опишем в этой главе), как мы показали в разделе 5.8 и в решении упражнения 12.2. На рис. 12.1 мы предполагаем, что очереди сообщений Posix реализованы в ядре, что также возможно. Но именованные и неименованные каналы и очереди сообщений System V требуют копирования данных из процесса в ядро вызовом write или msgsnd или копирования данных из ядра процессу вызовом read или msgrcv. 

Клиент считывает данные из канала IPC, что обычно требует их копирования из ядра в пространство процесса.

Наконец, данные копируются из буфера клиента (второй аргумент вызова write) в выходной файл.

Таким образом, для копирования файла обычно требуются четыре операции копирования данных. К тому же эти операции копирования осуществляются между процессами и ядром, что часто является дорогостоящей операцией (более дорогостоящей, чем копирование данных внутри ядра или внутри одного процесса). На рис. 12.1 изображено перемещение данных между клиентом и сервером через ядро. 

UNIX: взаимодействие процессов

Рис. 12.1. Передача содержимого файла от сервера к клиенту


Недостатком этих форм IPC — именованных и неименованных каналов — является то, что для передачи между процессами информация должна пройти через ядро.

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

Теперь информация передается между клиентом и сервером в такой последовательности:

сервер получает доступ к объекту разделяемой памяти, используя для синхронизации семафор (например);

 сервер считывает данные из файла в разделяемую память. Второй аргумент вызова read (адрес буфера) указывает на объект разделяемой памяти;

 после завершения операции считывания клиент уведомляется сервером с помощью семафора;

 клиент записывает данные из объекта разделяемой памяти в выходной файл. 

UNIX: взаимодействие процессов

Рис. 12.2. Копирование файла через разделяемую память


Этот сценарий иллюстрирует рис. 12.2.

Из этого рисунка видно, что копирование данных происходит всего лишь дважды: из входного файла в разделяемую память и из разделяемой памяти в выходной файл. Мы нарисовали два прямоугольника штриховыми линиями; они подчеркивают, что разделяемая память принадлежит как адресному пространству клиента, так и адресному пространству сервера.

Концепции, связанные с использованием разделяемой памяти через интерфейсы Posix и System V, похожи. Первый интерфейс описан в главе 13, а второй — в главе 14.

В этой главе мы возвращаемся к примеру с увеличением последовательного номера, который впервые появился в главе 9. Теперь мы будем хранить последовательный номер в сегменте разделяемой памяти, а не в файле.

Сначала мы подчеркнем, что память разделяется между родительским и дочерним процессами при вызове fork. В пpoгрaммe из листинга 12.1[1] родительский и дочерний процессы по очереди увеличивают глобальный целочисленный счетчик count.


ЧАСТЬ 4 РАЗДЕЛЯЕМАЯ ПАМЯТЬ | UNIX: взаимодействие процессов | Листинг 12.1. Увеличение глобального счетчика родительским и дочерним процессами