Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
практична робота 4.doc
Скачиваний:
3
Добавлен:
25.11.2019
Размер:
206 Кб
Скачать
☆

Дескриптори System V ipc

Ми говорили, що інформацію про потоки уведення-виведення, з якими має справу поточний процес, зокрема про pip'и і FIFO, операційна система зберігає в таблиці відкритих файлів процесу. Системні виклики, що здійснюють операції над потоком, використовують як параметр індекс елемента таблиці відкритих файлів, відповідного потоку, – файловий дескриптор. Використовування файлових дескрипторів для ідентифікації потоків усередині процесу дозволяє застосовувати до них вже існуючий інтерфейс для роботи з файлами, але в той же час приводить до автоматичного закриття потоків при завершенні процесу. Цим, зокрема, пояснюється один з перерахованих вище недоліків потокової передачі інформації.

При реалізації компонентів System V IPC була прийнята інша концепція. Ядро операційної системи зберігає інформацію про всі засоби System V IPC, що використовуються в системі, зовні контексту призначених для користувача процесів. При створенні нового засобу зв'язку або отриманні доступу до вже існуючого, процес одержує ненегативне ціле число – дескриптор (ідентифікатор) цього засобу зв'язку, який однозначно ідентифікує його у всій обчислювальній системі. Цей дескриптор повинен передаватися як параметр всім системним викликам, що здійснюють подальші операції над відповідним засобом System V IPC.

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

Пам'ять, що розділяється, в unix. Системні виклики shmget(), shmat(), shmdt()

З погляду операційної системи, якнайменше семантично навантаженим засобом System V IPC є пам'ять, що розділяється (shared memory). Ми вже згадували про цю категорію засобів зв'язку на лекції. Для поточної роботи нам достатньо знати, що операційна система може дозволити декільком процесам спільно використовувати деяку область адресного простору.

Всі засоби зв'язку System V IPC вимагають попередніх дій (створення) для організації взаємодії процесів.

Для створення області пам'яті з певним ключем або доступу, що розділяється, по ключу до вже існуючої області застосовується системний виклик shmget(). Існує два варіанти його використовування для створення нової області пам'яті, що розділяється.

  • Стандартний спосіб. Як значення ключа системному виклику поставляється значення, сформоване функцією ftok() для деякого імені файлу і номера екземпляра області пам'яті, що розділяється. Як прапори поставляється комбінація прав доступу до створюваного сегменту і прапора IPC_CREAT. Якщо сегмент для даного ключа ще не існує, то система намагатиметься створити його з вказаними правами доступу. Якщо ж раптом він вже існував, то ми просто одержимо його дескриптор. Можливе додавання до цієї комбінації прапорів прапора IPC_EXCL. Цей прапор гарантує нормальне завершення системного виклику тільки в тому випадку, якщо сегмент був дійсно створений (тобто раніше він не існував), якщо ж сегмент існував, то системний виклик завершиться з помилкою, і значення системної змінної errno, описаної у файлі errno.h, буде встановлено в EEXIST.

  • Нестандартний спосіб. Як значення ключа указується спеціальне значення IPC_PRIVATE. Використовування значення IPC_PRIVATE завжди приводить до спроби створення нового сегменту пам'яті, що розділяється, із заданими правами доступу і з ключем, який не співпадає із значенням ключа жодного з вже існуючих сегментів і який не може бути одержаний за допомогою функції ftok() ні при одній комбінації її параметрів. Наявність прапорів IPC_CREAT і IPC_EXCL в цьому випадку ігнорується.

Системний виклик shmget()

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget(key_t key, int size

int shmflg);

Опис системного виклику

Системний виклик shmget призначений для виконання операції доступу до сегменту пам'яті, що розділяється, і, у разі його успішного завершення, повертає дескриптор System V IPC для цього сегменту (ціле ненегативне число, однозначно характеризуюче сегмент усередині обчислювальної системи і що використовується надалі для інших операцій з ним).

Параметр key є ключем System V IPC для сегменту, тобто фактично його ім'ям з простору імен System V IPC. Як значення цього параметра може використовуватися значення ключа, одержане за допомогою функції ftok(), або спеціальне значення IPC_PRIVATE. Використовування значення IPC_PRIVATE завжди приводить до спроби створення нового сегменту пам'яті, що розділяється, з ключем, який не співпадає із значенням ключа жодного з вже існуючих сегментів і який не може бути одержаний за допомогою функції ftok() ні при одній комбінації її параметрів.

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

Параметр shmflg – прапори – грає роль тільки при створенні нового сегменту пам'яті, що розділяється, і визначає права різних користувачів при доступі до сегменту, а також необхідність створення нового сегменту і поведінка системного виклику при спробі створення. Він є деякою комбінацією (за допомогою операції побітове або – "|") наступних приречених значень і вісімкових прав доступу:

  • IPC_CREAT – якщо сегменту для вказаного ключа не існує, він повинен бути створений;

  • IPC_EXCL – застосовується спільно з прапором IPC_CREAT. При сумісному їх використовуванні і існуванні сегменту з вказаним ключем, доступ до сегменту не проводиться і констатується помилкова ситуація, при цьому змінна errno, описана у файлі <errno.h>, прийме значення EEXIST;

  • 0400 – дозволено читання для користувача, що створив сегмент;

  • 0200 – дозволений запис для користувача, що створив сегмент;

  • 0040 – дозволено читання для групи користувача, що створив сегмент;

  • 0020 – дозволений запис для групи користувача, що створив сегмент;

  • 0004 – дозволено читання для всієї решти користувачів;

  • 0002 – дозволений запис для всієї решти користувачів.

Значення, що повертається

Системний виклик повертає значення дескриптора System V IPC для сегменту пам'яті при нормальному завершенні, що розділяється, і значення -1 при виникненні помилки.

Доступ до створеної області пам'яті, що розділяється, надалі забезпечується її дескриптором, який поверне системний виклик shmget(). Доступ до вже існуючої області також може здійснюватися двома способами:

  • Якщо ми знаємо її ключ, то, використовуючи виклик shmget(),можем одержати її дескриптор. В цьому випадку не можна указувати як складова частина прапорів прапор IPC_EXCL, а значення ключа, природно, не може бути IPC_PRIVATE. Права доступу ігноруються, а розмір області повинен співпадати з розміром, вказаним при її створенні.

  • Або ми можемо скористатися тим, що дескриптор System V IPC дійсний в рамках всієї операційної системи, і передати його значення від процесу, що створив пам'ять, що розділяється, поточному процесу. Відзначимо, що при створенні пам'яті, що розділяється, за допомогою значення IPC_PRIVATE – це єдино можливий спосіб.

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

Системний виклик shmat()

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

char *shmat(int shmid, char *shmaddr

int shmflg);

Опис системного виклику

Системний виклик shmat призначений для включення області пам'яті, що розділяється, в адресний простір поточного процесу. Даний опис не є повним описом системного виклику, а обмежується рамками поточного курсу. Для повного опису звертайтеся до UNIX Manual.

Параметр shmid є дескриптором System V IPC для сегменту пам'яті, що розділяється, тобто значенням, яке повернув системний виклик shmget() при створенні сегменту або при його пошуку по ключу.

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

Параметр shmflg в нашому курсі може приймати тільки два значення: 0 – для здійснення операцій читання і запису над сегментом і SHM_RDONLY – якщо ми хочемо тільки читати з нього. При цьому процес повинен мати відповідні права доступу до сегменту.

Значення, що повертається

Системний виклик повертає адресу сегменту пам'яті в адресному просторі процесу при нормальному завершенні, що розділяється, і значення -1 при виникненні помилки.

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

Системний виклик shmdt()

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/shm.h>

int shmdt(char *shmaddr);

Опис системного виклику

Системний виклик shmdt призначений для виключення області пам'яті, що розділяється, з адресного простору поточного процесу.

Параметр shmaddr є адресою сегменту пам’яті, що розділяється. е. значенням, яке повернув системний виклик shmat().

Значення, що повертається

Системний виклик повертає значення 0 при нормальному завершенні і значення -1 при виникненні помилки.