Программирование >>  Структура ядра и системные вызовы 

1 ... 54 55 56 [ 57 ] 58 59 60 ... 98


Утилита getsem, определенная в новом заголовке message.h, выполняет вызов semop с набором семафоров на основании фактических значений аргумента орТуре (они присваиваются либо серверным, либо клиентским процессом).

Функция-конструктор message открывает разделяемую область памяти и двухсемафорный набор. Эти два объекта имеют одинаковые ключевые идентификаторы. Если набор семафоров - совершенно новый объект, он инициализируется начальными значениями 0,1 (т.е. значение перюго семафора - О, а второго - 1).

Функция send передает сообщение в разделяемую область памяти. Поскольку операции, выполняемые функцией 5е/иоэ, в серверном и клиентском процессах разные, функция send используется с аргументом type, который позволяет ей определить, каким является вызывающий процесс - серверным или клиентским. Если значение аргумента type превышает 99, функцию вызывает клиентский процесс. В противном случае это серверный процесс. Данная функция блокирует вызов getsem до тех пор, пока процесс не сможет завершить свою операцию semap. После этого процесс записывает сообщение в разделяемую область памяти и вновь вызывает getsem для установки значений семафоров, которые разблокируют клиентский процесс.

Функция read действует аналогичным образом. Операции semop, с помощью которых обеспечивается чтение сообщений из разделяемой области памяти, в серверном и клиентском процессах выполняются по-разному. Чтобы определить, каким является вызывающий процесс, функция read использует аргумент туре. Если значение этого аргумента меньше нуля (реально это -99), вызывающий процесс - серверный; в противном случае - клиентский. Данная функция блокирует вызов getsem до тех пор, пока процесс не сможет завершить свою операцию semop. После этого процесс читает сообщение из разделяемой области памяти и сбрасывает семафоры в начальные значения О, 1 (если процесс - клиентский).

Функция г/я Q вызывается в том случае, если серверный процесс получает от клиентского процесса команду QUIT CMD. Данная функция вызывает API semctl и shmctl для удаления набора семафоров и разделяемой области памяти, а затем для заверщения серверного процесса. Это необходимо потому, что семафоры и разделяемая область памяти - устойчивые объекты, т.е. они сохраняются в адресном пространстве ядра даже после завершения процессов, которые их создали.

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

chpl3 % mserver & [1] 356

server: start execution... chpia % mclient client: start execution... cmd> 1

server: receive cmd fl, from client: 338 Tue Jan 26 21:50. cmd> 2 server:

client: 59 1995

receive cmd t2,from client: client: 338 Fri Jan 27 05:51:19 1995 cmd> 4

server: receive cmd t4, from client: 338 client: 338 Illegal cmd: 4 cmd> 3

client: 338 exiting... server: receive cmd t3, from client client: deleting msg queue... 11] Done mserver chpl3%

10.8. Ввод-вывод с отображением в память

API ттар был впервые предложен в BSD UNIX. Он позволяет процессу отображать свое виртуальное адресное пространство непосредственно на страницу памяти файлового объекта, находящуюся в пространстве ядра. Такой процесс может записывать данные файла непосредственно в эту отображенную область памяти и читать их из нее. Более того, если отображение в один файловый объект одновременно осуществляют несколько процессов, то они совместно используют отображенную область памяти. Эти процессы могут взаимодействовать друг с другом приблизительно так же, как тфи использовании разделяемой памяти.

API ттар отличается от обычных файловых API ОС UNIX тем, что если файл открывается с помощью вызова read (для чтения данных из файла), тО ядро выбирает одну или несколько страниц затребованных данных из области на жестком диске, в которой хранится файл. Эти данные затем помещаются в отображенную область памяти ядра и копируются в буфер находящийся в виртуальном адресном пространстве вызывающего процесса. В API write происходит обратное: когда процесс вызывает write для записи данных в файл, ядро копирует эти данные из буфера процесса в свою область памяти. Когда эта область заполняется или если процесс требует освободить буфер, данные копируются в файл, находящийся на жестком диске.

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

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



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

Еще один вариант применения API ттар - эмуляция функции разделяемой памяти. Два и более процессов, которые должны взаимодействовать между собой, могут с помощью ттар осуществить отображение в один файловый объект. После этого они могут читать и записывать данные друг друга через свои отображенные виртуальные адреса. Ниже мы покажем, как с помощью ттар можно реализовать приложение клиент/сервер, рассмотренное в предыдущем разделе.

10.8.1. API ввода-вывода с отображением в память

Все API семейства ттар объявляются в заголовке <sys/mman.h>.

Назначение

mmap Отображает виртуальное адресное пространство процесса в адресное пространство файлового объекта

munmap Отсоединяет виртуальный адрес процесса от файлового объекта

msync Синхронизирует данные в отображенной области памяти с данными соответствующего файлового объекта, хранящегося на жестком диске

10.8.2. Функция mmap

Прототип функции ттар имеет следующий вид:

#include <sys/types.h> #include <sys/mman.h>

caddr t mmap ( caddr t addr, Int size, Int prot, int flags, int fd, off t pos );

Эта функция отображает файловый объект, указанный аргументом fd, в виртуальное адресное пространство процесса, начиная с адреса addr. Если аргумент addr равен нулю, ядро само назначает виртуальный адрес для отображения. Аргумент pos задает начальную позицию в файловом объекте, который отображается в addr. Его значение должно быть либо равным нулю, либо кратным размеру страницы памяти (для получения значения размера страницы системной памяти можно воспользоваться API getpagesize или sysconf}. Аргумент prot задает права доступа к отображенной памяти. Он может иметь одно из следующих значений;

Значение prot Смысл

PROT READ Данные, находящиеся в отображенной области памяти, можно читать

PROT WRITE В отображенную область памяти можно записывать PROT EXEC Содержимое отображенной области памяти - исполняемый код

Аргумент flags залает опции отображения. Он может иметь одно из следующих значений:

Значение flags Смысл

MAP SHARED

MAP PRIVATE

MAP FIXED

Данные, записанные в отображенную область памяти, доступны другим процессам, которые отображаются в этот же файловый объект

Данные, записанные в отображенную область, недоступны другим процессам, которые отображаются в этот же файловый объект

Значение addr должно бьпь начальным виртуальным адресом отображенной области. Если отображение не может быть выполнено, функция возвращает код неудачного завершения. Если данный флаг не указан или если флаг MAP VARIABLE определен и задан системой, то ядро может вместо addr выбрать для отображаемой области другой виртуальный адрес

Рассматриваемая функция возвращает фактический виртуальный адрес, с которого начинается отображенная область памяти. В случае неудачи возвращается MAP FAILED.

Флаг PROT EXEC используется в том случае, если отображаемый файловый объект - исполняемый файл и вызывающий процесс имеет права привилегированного пользователя. Когда пользователь вызывает команду в UNIX-системе, ядро обычно вьшолняет функцию ттар с исполняемым файлом этой команды. Содержимое исполняемого файла перед выполнением считывается непосредственно из области памяти, в которой отображен данный файл.

Флаг MAP PRIVATE указывает на то, что все данные, записываемые в отображенную область памяти, невидимы для остальных процессов, отображенных в адресное пространство этого же файлового объекта. При этом, однако, названный флаг запрещает также и обратное сохранение данных (т.е. сохранение данных, записанных в отображенной области памяти, в файле, находящемся на диске). Предположим, что процессы А и Б отображаются в файл FOO, при этом процесс А установил флаг MAP PRIVATE, а процесс Б - флаг MAP SHARED. Если процесс Б запишет данные в отображенную область памяти раньше, чем это сделает процесс А, новые данные будут видимы обоим процессам. Когда процесс А записывает данные в совместно используемую отображенную область памяти, ядро создает отдельную копию страниц памяти, которые этот процесс изменил, тогда как процесс Б продолжает работать со старой страницей. С этого момента все данные, которые процесс А записывает на свою страницу памяти, перестают быть видимыми для процесса Б, и наоборот.



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

Перед тем как вызывать функцию ттар для отображения файла, процесс должен вызвать API open и присвоить аргументу fd дескриптор открываемого файла. Кроме того, если этот файловый объект создается вызовом open заново, процесс должен записать в него для инициализации как минимум size байтов. Это делается потому, что ттар не вьщеляет память, а просто отмечает, что виртуальное адресное пространство процесса (от addr до addr+size) разрещается использовать. Если размер файла меньше, то ядро не вьщеляет память за пределами страницы, содержащей виртуальный адрес addr+<file size>. Процесс, обращающийся к данным, расположенным между addr+<file size> и addr+size, может получить сигнал SIGBUS.

Приведенная ниже программа test mmap.C открывает новый файл с именем F00 размером SHMSIZE байтов (инициализированных значением \0 ), а затем закрывает дескриптор файла fd, потому что он больше не нужен. Наконец, процесс записывает в отображенную область памяти строку Hello и завершается. Если пользователь просмотрит содержимое этого файла, воспользовавшись для этого комавдой cat, он заметит, что файл содержит строку Hello.

♦include <strstream.h>

♦include <stdio.h>

♦include <stdlib.h>

♦include <unistd.h>

♦include <fcntl.h>

♦include <sys/mman.h>

const int SHMSIZE = 1024;

♦ifndef MMAP FAILED

♦define MMPAP FAILED (caddr t*)0

fendif

int main() {

int ch=\0, fd = open ( FOO , 0 CREAT0 EXCL,0666);

if (fd==-l) { perror( file exists ), exit(l); };

for (int i=0; i < SHMSIZE; i++) /* инициализировать файл */

, write(fd, Sch, 1);

caddr t memP=mmap(0,SHMSIZE,PROT READIPROTJWRITE, MAP SHARED,fd, 0); if (memP==MAP FAILED) (

perror( mmap );

exit(2);

close(fd); /* этот файл больше не нужен */

ostrstream(memp,SHMSIZE) Hello UNIX\n ; return 0;

10.8.3. Функция munmap

Прототип функции munmap имеет следующий вид:

#include <sys/types.h> #include <sys/mmap.h>

int munmap ( caddr t addr, int size );

Эта функция отсоединяет отображенную область памяти от виртуального адресного пространства процесса. Освобождаемая область начинается с виртуального адреса addr и заканчивается страницей памяти, имеющей виртуальный адрес addr+size.

В случае успешного выполнения данная функция возвращает О, а в случае неудачи -1.

10.8.4 Функция msync

Прототип функции msync выглядит следующим образом:

#include <sys/types.h> #include <sys/mmap.h>

int msync ( caddr t addr, int size, int flags );

Эта функция синхронизирует данные, находящиеся в отображенной области памяти, с соответствующими данными файлового объекта, имеющегося на жестком диске. Если аргумент size равен нулю, в отображенной области синхронизируются все измененные страницы, начинающиеся с addr. Если size больше нуля, то синхронизируются только те страницы, которые находятся в интервале от addr до addr+size.

Аргумент flags задает метод синхронизации и может иметь одно из следующих значений:

Значение flags Смысл

MS SYNC MS ASYNC MS IN VALIDATE

Записать данные из отображенной области памяти на жесткий диск. Ждать завершения записи данных

Записать данные из отображенной области памяти на жесткий диск. Не ждать завершения записи данных

Аннулировать данные в отображенной области памяти. Следующее обращение к этой области приведет к выборке с . жесткого диска новых страниц

В случае успешного вьшолнения рассматриваемая функция возвращает О, а в случае неудачи -1.



1 ... 54 55 56 [ 57 ] 58 59 60 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика