Материал: 6261

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

171

У каждого процесса, в системе Linux, есть адресное пространство, разделенное на

3 логических сегмента:

text segment

Содержит машинные команды, образующие исполняемый код

 

программы, который создается компилятором и ассемблером при

 

транс-ляции программы в машинный код (только для чтения).

data segment

Содержит переменные, строки, массивы и другие данные прог-

 

раммы и состоит из двух частей: инициализированные данные и

 

не-инициализированные данные.

 

Инициализированная часть сегмента данных содержит

 

переменные и константы компилятора, значения которых должны

 

быть заданы при запуске.

 

Все переменные, в неинициализированной, части должны быть

 

сброшены в 0.

stack segment

Выделяется отдельный сегмент на каждую нить (thread) процесса.

 

На большинстве компьютеров он начинается около старших ад-

 

ресов виртуального адресного пространства и растет вниз к 0.

 

Если указатель стека оказывается ниже нижней границы стека, то

 

происходит аппаратное прерывание, при котором операционная

 

система понижает границу сегмента стека на одну страницу.

 

Когда программа запускается, ее стек не пуст, он содержит все

 

переменные окружения, а также командную строку, введенную в

 

оболочке (shell) для вызова этой программы.

Если рассмотреть только эти три сегмента, то можно заметить:

•системные вызовы fork(...), _exit(...) и exec*(...), косвенно вызывают подсистему управления памятью и изменяют ее виртуальное пространство;

•сегменты text и stack недоступны для прямого изменения самому процессу, поскольку напрямую управляются ядром ОС, обеспечивая его существование и функционирование;

•процессу недоступно прямое управление первой часть сегмента data, поскольку эта часть статически сформирована компилятором языка;

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

Таким образом, процесс может воспользоваться только четырьмя функциями, реализованными в стандарте языка С:

#include <stdlib.h>

void *malloc(size_t size); # выделение нужного размера памяти;

void free(void *ptr);

# освобождение выделенного участка памяти;

void

*calloc(size_t nmemb, size_t size);

#

выделение

памяти для массива;

void

*realloc(void *ptr, size_t size);

#

изменение

размера выделенной памяти.

Кроме того, процессу доступны системные вызовы, изменяющие адрес конца сегмента data:

172

#include <unistd.h>

int brk(void *addr); # установка адреса конца сегмента data void *sbrk(intptr_t increment); # добавление памяти сегменту data

Адреса окончаний сегментов процесса доступны ему через внешние переменные:

etext

Первый адрес, после окончания сегмента кода процесса;

edate

Первый адрес после инициализированных данных сегмента data;

end

Первый адрес после неинициализированных данных сегмента data, извест-

 

ный как BSS segment.

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

#include <stdio.h> #include <stdlib.h>

extern char etext, edata, end; /* The symbols must have some type,

 

or "gcc -Wall" complains */

int

 

 

main(int argc, char *argv[])

 

{

 

 

printf("First address past:\n");

 

printf("

program text (etext)

%10p\n", &etext);

printf("

initialized data (edata)

%10p\n", &edata);

printf("

uninitialized data (end)

%10p\n", &end);

exit(EXIT_SUCCESS);

}

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

Современные ядра ОС содержат множество механизмов для взаимодействия процессов. Одним из первых и базовым является механизм, известный как набор средств IPC.

IPC — InterProcess Communication — межпроцесная коммуникация, включает всебя механизмы: синхронизации, разделения памяти, обмена сообщениями и удаленный вызов процедур (RPC — Remote Procedure Call).

Мы, в данной теме, рассмотрим только механизмы разделения памяти и обмен сообщениями.

173

6.11 Системные вызовы и разделяемая память

Первоначально, все процессы ОС максимально разделены и защищены.

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

Базовые средства взаимодействия процессов обеспечиваются:

•средствами поддержки «жизненного цикла процесса»: порождая, модифицируя и завершая процессы;

•механизмом сигналов: распространяя и принимая сигналы, а также обеспе-

чивая корректные действия на их наличие.

Преимущество базовых средств взаимодействия процессов — высокая скорость и эффективность их использования.

Недостатки:

•необходимость одновременного существования группы взаимодействующих процессов;

•слабая информативность сигналов, требующая хорошего знания их семантики и алгоритмов работы ядра ОС.

Альтернативный подход к взаимодействию процессов - использование возможностей файловой системы ОС.

Преимущество: возможность использования любых средств взаимодействия.

Недостатки:

•алгоритмическая сложность разрешения всех тупиковых ситуаций, возникающих в приложениях;

•необходимость реализации средств взаимодействия непосредственно в приложениях;

•неэффективная и ненадежная реализация взаимодействия процессов, слабо обеспеченная возможностями ядра ОС;

•локальная семантика и интерпретация механизмов взаимодействия ограничивающая переносимость самих приложений.

Комбинированные подходы к взаимодействию процессов:

•максимальное использование возможностей ядра ОС;

•разработка новых эффективных алгоритмов взаимодействия процессов, ко-

торые включаются в функционал ядра ОС.

Одним из таких подходов является проект IPC - InterProcess Communication, который предполагает, что:

•все процессы, желающие взаимодействовать, обращаются к ядру ОС и получают от него уникальный ключ;

•используя уникальный ключ, процессы создают в ядре ОС свои ресурсы и пот-

ребляют ресурсы, уже созданные другими процессами.

Генерация уникального ключа осуществляется ядром ОС посредством системного вызова:

174

#include <sys/types.h>

#include <sys/ipc.h>

key_t ftok(char *pathname, int proj_id);

где параметры:

pathname - должен являться указателем на имя существующего файла, доступного для процесса, вызывающего функцию;

proj_id – это небольшое целое число, характеризующее экземпляр средства связи.

Замечание

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

Таким образом, для взаимодействия процессов посредством IPC, разработчикам приложений необходимо договориться:

•об именовании своего взаимодействия, что определяется двумя параметрами: именем существующего в ОС файла и номера варианта его использования;

•выбора способа взаимодействия, поддерживаемого IPC;

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

Вданном подразделе, мы рассмотрим основную идею способа взаимодействия, основанного на совместном использовании оперативной памяти ЭВМ и получившего название разделяемой памяти IPC.

Встандарте POSIX-2001 разделяемый объект памяти определяется как объект, представляющий собой память ЭВМ, которая может быть параллельно отображена в адресное пространство более чем одного процесса.

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

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

Таким образом, вариант взаимодействия с помощью разделяемой памяти обеспечивает процессам:

•асинхронный способ взаимодействия, не требующий одновременного существования всех взаимодействующих процессов;

•наиболее быстрый доступ к общим структурированным данным.

Непосредственная работа с сегментами разделяемой памяти обеспечивается с помощью четырех системных вызовов:

175

#include <sys/shm.h>

int shmget (key_t key, size_t size, int shmflg);

void *shmat (int shmid, const void *shmaddr, int shmflg); int shmdt (const void *shmaddr);

int shmctl (int shmid, int cmd, struct shmid_ds *buf);

Семантическое назначение этих вызовов следующее:

shmget

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

 

ные права доступа к нему и его размер в байтах. Возвращает

 

идетификатор памяти, при подключении сегмента к процессу или для

 

управления им.

shmat

Подключает виртуальный адрес процесса, указывающий на используе-

 

мую структуру данных к сегменту памяти с заданным иденитифика-

 

тором. Возвращает адрес разделяемого сегмента.

shmdt

Отключает адрес разделяемого сегмента от виртуального адреса про-

 

цесса.

shmctl

Управляет разделяемым сегментом посредством команд и данных спе-

 

циальной структуры. В частности, удаляет разделяемый сегмент.

Замечание

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

Средства межпроцессного взаимодействия System V IPC имеют также две специальные утилиты, которые могут использоваться из командной строки или в сценариях языка shell:

•ipcs - вывод отчёта о состоянии средств межпроцессного взаимодействия;

•ipcrm - удаление очередей сообщений, наборов семафоров и разделяемых сегментов памяти.

Ощий синтаксис этих утилит:

ipcs [-abcmopqstMQSTy] [-C дамп] [-N система] [-u пользователь]

ipcrm [-q msqid] [-m shmid] [-s semid] [-Q msgkey] [-M shmkey]

[-S semkey] ...

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

Источник: https://studfile.net/preview/16438529/