Пам'ять, що розділяється, як спосіб міжпроцесової взаємодії

Це спеціальний механізм, за допомогою якого засобами операційної системи два процеси можуть звертатися до загальної ділянки фізичної пам'яті — кожен через свій адресний простір.

Рис. 8.1 Пам'ять, що розділяється.

Для ОС даний спосіб міжпроцесової| взаємодії є|з'являється,являється| найбільш простим з погляду реалізації і продуктивним. Від ОС потрібно виділити область фізичної пам'яті і дозволити всім процесам звертатися|обертатися| до цієї області як до своєї власної. Проте|однак| для програмістів цей спосіб є|з'являється,являється| найскладнішим і ненадійним, оскільки не можна гарантувати, що «потрібні» дані одного процесу не будуть заміщені даними інших процесів. Пам'ять, що з цієї причини розділяється, використовується в окремих випадках, коли потрібна висока продуктивність.

Для роботи з|із| пам'яттю, що розділяється, використовуються чотири системні виклики:

· shmget створює новий сегмент пам'яті, що розділяється, або знаходить|находить| існуючий сегмент з|із| тим же ключем|джерелом|;

· shmat підключає сегмент з|із| вказаним дескриптором до віртуальної пам'яті процесу, що звертається|обертається|;

· shmdt відключає від віртуальної пам'яті раніше підключений до неї сегмент з|із| вказаною віртуальною адресою начала|розпочала,зачала|;

· нарешті|урешті|, системний виклик shmctl служить для управління різноманітними|всілякими| параметрами, пов'язаними з існуючим сегментом.

Після того, як сегмент пам'яті, що розділяється, підключений до віртуальної пам'яті процесу, цей процес може звертатися|обертатися| до відповідних елементів пам'яті з використанням звичайних|звичних| машинних команд читання і запису, не вдаючись до використання додаткових системних викликів.

Синтаксис системного виклику shmget виглядає таким чином:

shmid = shmget(key, size, flag);

Параметр size визначає бажаний розмір сегменту в байтах. Далі робота відбувається|походить| за загальними|спільними| правилами. Якщо в таблиці пам'яті, що розділяється, знаходиться|перебуває| елемент, що містить|утримує| заданий ключ|джерело|, і права доступу не суперечать|перечать| поточним характеристикам процесу, що звертається|обертається|, то значенням системного виклику є|з'являється,являється| дескриптор існуючого сегменту. Інакше створюється новий сегмент з|із| розміром не менше встановленого|установленого| в системі мінімального розміру сегменту пам'яті, що розділяється, і не більше встановленого|установленого| максимального розміру. Створення|створіння| сегменту не означає негайного виділення під нього основної пам'яті. Ця дія відкладається до виконання першого системного виклику підключення сегменту до віртуальної пам'яті деякого процесу. Аналогічно, при виконанні останнього системного виклику відключення сегменту від віртуальної пам'яті відповідна основна пам'ять звільняється|визволяється|.

Підключення сегменту до віртуальної пам'яті виконується шляхом звернення до системного виклику shmat:

virtaddr = shmat(id, addr, flags);

Тут id - це раніше одержаний|отриманий| дескриптор сегменту, а addr - бажана процесом віртуальна адреса, яка повинна відповідати початку сегменту у віртуальній пам'яті. Значенням системного виклику є|з'являється,являється| реальна віртуальна адреса початку сегменту (його значення не обов'язково співпадає|збігається| із|із| значенням прямого параметра addr). Якщо значенням addr є|з'являється,являється| нуль, ядро вибирає найбільш зручну віртуальну адресу початку сегменту.

Для відключення сегменту від віртуальної пам'яті використовується системний виклик shmdt:

shmdt(addr);

де addr - це віртуальна адреса початку сегменту у віртуальній пам'яті, раніше одержана|отримана| від системного виклику shmat.

Системний виклик shmctl:

shmctl(id, cmd, shsstatbuf);

містить|утримує| прямий параметр cmd, що визначає потрібну дію, і призначений для виконання різних функцій. Найбільш важливою|поважною| є|з'являється,являється| функція знищення сегменту пам'яті, що розділяється. Знищення сегменту проводиться|виробляється,справляється| таким чином. Якщо до моменту виконання системного виклику жоден процес не підключив сегмент до своєї віртуальної пам'яті, то основна пам'ять, займана|позичати,посідати| сегментом, звільняється|визволяється|, а відповідний елемент таблиці сегментів, що розділяються, оголошується вільним. Інакше в елементі таблиці сегментів виставляється прапор, що забороняє виконання системного виклику shmget по відношенню до цього сегменту, але|та| процесам, що встигли|устигнули| одержати|отримати| дескриптор сегменту, як і раніше дозволяється підключати сегмент до своєї віртуальної пам'яті. При виконанні останнього системного виклику відключення сегменту від віртуальної пам'яті операція знищення сегменту завершується.

 

int main()

{

int segment_id;

char *shared_memory;

struct shmid_ds shmbuffer;

int segment_size;

const int shared_segment_size = 0x6400;

segment_id = shmget(IPC_PRIVATE, shared_segment_size, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);

shared_memory = (char*) shmat(segment_id, 0, 0);

printf("\n Спільна пам'ять додана за адресою: %p", shared_memory);

shmctl(segment_id, IPC_STAT, &shmbuffer);

segment_size = shmbuffer.shm_segsz;

printf("\n Розмір сегменту: %d", segment_size);

sprintf(shared_memory, "Hello, World!");

shmdt(shared_memory);

shared_memory = (char*)shmat(segment_id, (void*)0x5000000, 0);

printf("\n Спільну пам'ять перемістили за адресою: %p", shared_memory);

printf("\n %s\n\n", shared_memory);

shmdt(shared_memory);

shmctl(segment_id, IPC_RMID, 0);

return 0;

}