У вас вопросы?
У нас ответы:) SamZan.net

семафорами від класичних операцій

Работа добавлена на сайт samzan.net: 2015-07-05

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 8.3.2025

Практичне заняття 5

Семафори в UNIX як засіб синхронізації процесів 

Мета: Розглянути та практично опрацювати наступні питання: Семафори в UNIX. Відмінність операцій над UNIX-семафорами від класичних операцій. Створення масиву семафорів або доступ до вже існуючого масиву. Системний виклик semget(). Виконання операцій над семафорами. Системний виклик semop(). Видалення набору семафорів з системи за допомогою команди ipcrm або системного виклику semctl(). Поняття про POSIX-семафори.

Семафори в UNIX. Відмінність операцій над UNIX-семафорами від класичних операцій

В матеріалах попереднього заняття йшлося про необхідність синхронізації роботи процесів для їх коректної взаємодії через пам'ять, що розділяється. Як згадувалося в лекції 6, одним з перших механізмів, запропонованих для синхронізації поведінки процесів, стали семафори, концепцію яких описав Дейкстра (Dijkstra) в 1965 році. При розробці засобів System V IPC семафори увійшли до їх складу як невід'ємна частина. Слід зазначити, що набір операцій над семафорами System V IPC відрізняється від класичного набору операцій {P, V}, запропонованого Дейкстрой. Він включає три операції:

  •  А(S, n) – збільшити значення семафора S на величину n;
  •  D(S, n) – поки значення семафора S < n, процес блокується. Далі S = S - n; 
  •  Z(S) – процес блокується до тих пір, поки значення семафора S не стане рівним 0.

Спочатку всі IPC-семафори ініціюються нульовим значенням.

Ми бачимо, що класичній операції P(S) відповідає операція D(S,1), а класичній операції V(S) відповідає операція А(S,1). Аналогом ненульової ініціалізації семафорів Дейкстри значенням n може служити виконання операції А(S,n) відразу після створення семафора S, із забезпеченням атомарності створення семафора і її виконання за допомогою іншого семафора. Ми показали, що класичні семафори реалізуються через семафори System V IPC. Зворотне не є вірним. Використовуючи операції P(S) і V(S), ми не зуміємо реалізувати операцію Z(S).

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

Створення масиву семафорів або доступ до вже існуючого. Системний виклик semget()

В цілях економії системних ресурсів операційна система UNIX дозволяє створювати не по одному семафору для кожного конкретного значення ключа, а пов'язувати з ключем цілий масив семафорів (в Linux – до 500 семафорів в масиві, хоча ця кількість може бути зменшене системним адміністратором). Для створення масиву семафорів, асоційованого з певним ключем, або доступу по ключу до вже існуючого масиву використовується системний виклик semget(), є аналогом системного виклику shmget() для пам'яті, що розділяється, який повертає значення IPC-дескриптора для цього масиву. При цьому застосовуються ті ж способи створення і доступу, що і для пам'яті, що розділяється. Знов створені семафори ініціюються нульовим значенням.

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

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semget(key_t key, int nsems int semflg);

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

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

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

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

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

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

  •  0400 — дозволено читання для користувача, що створив масив
  •  0200 — дозволений запис для користувача, що створив масив
  •  0040 — дозволено читання для групи користувача, що створив масив
  •  0020 — дозволений запис для групи користувача, що створив масив
  •  0004 — дозволено читання для всієї решти користувачів
  •  0002 — дозволений запис для всієї решти користувачів

Знов створені семафори ініціюються нульовим значенням.

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

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

Виконання операцій над семафорами. Системний виклик semop()

Для виконання операцій А, D і Z над семафорами з масиву використовується системний виклик semop(), володіючий досить складною семантикою. Розробники System V IPC явно перенавантажували цей виклик, застосовуючи його не тільки для виконання всіх трьох операцій, але ще і для декількох семафорів в масиві IPC-семафорів одночасно. Для правильного використовування цього виклику необхідно виконати наступні дії:

  1.  Визначитися, для яких семафорів з масиву належить виконати операції. Необхідно мати у вигляді, що всі операції реально скоюються тільки перед успішним поверненням з системного виклику, тобто якщо ви хочете виконати операції А(S1,5) і Z(S2) в одному виклику і виявилося, що S2 != 0, те значення семафора S1 не буде змінено до тих пір, поки значення S2 не стане рівним 0. Порядок виконання операцій у разі, коли процес не переходить в стан очікування, не визначений. Так, наприклад, при одночасному виконанні операцій А(S1,1) і D(S2,1) у разі S2 > 1 невідомо, що відбудеться раніше – зменшиться значення семафора S2 або збільшиться значення семафора S1. Якщо порядок для вас важливий, краще застосувати декілька викликів замість одного.
  2.  Після того, як ви визначилися з кількістю семафорів і скоюваними операціями, необхідно завести в програмі масив з елементів типу struct sembuf з розмірністю, рівною певній кількості семафорів (якщо операція скоюється тільки над одним семафором, можна, природно, обійтися просто змінній). Кожний елемент цього масиву відповідатиме операції над одним семафором.
  3.  Заповнити елементи масиву. В полі sem_flg кожного елемента потрібно занести значення 0 (інші значення прапорів в семінарах ми розглядати не будемо). В поля sem_num і sem_op слід занести номери семафорів в масиві IPC семафорів і відповідні коди операцій. Семафори нумеруються, починаючи з 0. Якщо у вас в масиві всього один семафор, то він матиме номер 0. Операції кодуються так:
    •  для виконання операції А(S,n) значення поля sem_op повинне бути рівно n;
    •  для виконання операції D(S,n) значення поля sem_op повинне бути рівно –n;
    •  для виконання операції Z(S) значення поля sem_op повинне бути рівно 0.
  4.  Як другий параметр системного виклику semop() вказати адресу заповненого масиву, а як третій параметр – раніше певна кількість семафорів, над якими скоюються операції.

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

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semop(int semid, struct sembuf *sops int nsops);

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

Системний виклик semop призначений для виконання операцій А, D і Z (див. опис операцій над семафорами з масиву IPC семафорів – роздягнув "Створення масиву семафорів або доступ до вже існуючого. Системний виклик semget()" цього семінару). Даний опис не є повним описом системного виклику, а обмежується рамками поточного курсу. Для повного опису звертайтеся до UNIX Manual.

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

Кожний з nsops елементів масиву, на який указує параметр sops, визначає операцію, яка повинна бути вчинена над яким-небудь семафором з масиву IPC семафорів, і має тип структури struct sembuf, в яку входять наступні змінні:

  •  short sem_num — номер семафора в масиві IPC семафорів (нумеруються, починаючи з 0);
  •  short sem_op — виконувана операція;
  •  short sem_flg — прапори для виконання операції. В нашому курсі завжди рахуватимемо цю змінну рівної 0.

Значення елемента структури sem_op визначається таким чином:

  •  для виконання операції А(S,n) значення повинне бути рівно n;
  •  для виконання операції D(S,n) значення повинне бути рівно -n;
  •  для виконання операції Z(S) значення повинне бути рівно 0.

Семантика системного виклику має на увазі, що всі операції будуть в реальності виконані над семафорами тільки перед успішним поверненням з системного виклику. Якщо при виконанні операцій D або Z процес перейшов в стан очікування, то він може бути вывеен з цього стану при виникненні наступних форс-мажорних ситуацій:

  •  масив семафорів був видалений з системи;
  •  процес одержав сигнал, який повинен бути оброблений.

В цьому випадку відбувається повернення з системного виклику з констатацією помилкової ситуації.

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

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

Прогін прикладу з використанням семафора

Для ілюстрації сказаного розглянемо найпростіші програми, що синхронізують свої дії за допомогою семафорів

/* Програма 08-1a.c для ілюстрації роботи з семафорами */

/* Ця програма дістає доступ до одного системного семафора чекає, поки його значення не стане більше або рівним 1 після запусків програми 08-1b.c,а потім зменшує його на 1*/

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <stdio.h>

int main()

{

int semid; /* IPC дескриптор для масиву IPC семафорів */

char pathname[] = "08-1a.c"; /* Ім'я файлу що використовується для генерації ключа. Файл з таким  ім'ям винен існувати в поточній директорії */

key_t key; /* IPC ключ */

struct sembuf mybuf; /* Структура для завдання операції над семафором */

/* Генеруємо IPC-ключ з імені файлу 08-1a.c в поточній директорії і номери екземпляра масиву семафорів 0 */

if((key = ftok(pathname,0)) < 0){

 printf("Can\'t generate key\n");

 exit(-1);

}

/* Намагаємося дістати доступ по ключу до масиву семафорів, якщо він існує, або створити його з одного семафора, якщо його ще не існує, з правами доступу read & write для всіх користувачів */

if((semid = semget(key, 1, 0666 | IPC_CREAT)) < 0){

 printf("Can\'t get semid\n");

 exit(-1);

}

/* Виконаємо операцію D(semid1,1) для нашого масиву семафорів. Для цього спочатку заповнимо нашу структуру. Прапор, як завжди, вважаємо рівним 0. Наш масив семафорів складається з одного семафора з номером 0. Код операції -1.*/

mybuf.sem_op = -1;

mybuf.sem_flg = 0;

mybuf.sem_num = 0;

if(semop(semid &mybuf, 1)< 0){

 printf("Can\'t wait for condition\n");

 exit(-1);

}

printf("Condition is present\n");

return 0;

}

Лістинг 8.1. Програма 08-1a.c для ілюстрації роботи з семафорами

/* Програма 08-1b.c для ілюстрації роботи з

семафорами */

/* Ця програма дістає доступ до одного системного семафораі збільшує його на 1*/

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

#include <stdio.h>

int main()

{

int semid; /* IPC дескриптор для масиву IPC семафорів */

char pathname[] = "08-1a.c"; /* Ім'я файлу що використовується для генерації ключа. Файл з таким ім'ям винен існувати в поточній директорії */

key_t key; /* IPC ключ */

struct sembuf mybuf; /* Структура для завдання операції над семафором */

/* Генеруємо IPC ключ з імені файлу 08-1a.c в поточній директорії і номери екземпляра масиву семафорів 0 */

if((key = ftok(pathname,0)) < 0){

 printf("Can\'t generate key\n");

 exit(-1);

}

/* Намагаємося дістати доступ по ключу до масиву семафорів, якщо він існує, або створити його з одного семафора, якщо його ще не існує, з правами доступу read & write для всіх користувачів */

if((semid = semget(key, 1, 0666 | IPC_CREAT)) < 0){

 printf("Can\'t get semid\n");

 exit(-1);

}

/* Виконаємо операцію А(semid1,1) для нашого масиву семафорів. Для цього спочатку заповнимо нашу структуру. Прапор, як завжди  вважаємо рівним 0. Наш масив семафорів складається з одного семафора з номером 0. Код операції 1.*/

mybuf.sem_op = 1;

mybuf.sem_flg = 0;

mybuf.sem_num = 0;

if(semop(semid &mybuf, 1)< 0){

 printf("Can\'t wait for condition\n");

 exit(-1);

}

printf("Condition is set\n");

return 0;

}

Лістинг 8.1b. Програма 08-1b.c для ілюстрації роботи з семафорами

Перша програма виконує над семафором S операцію D(S,1), друга програма виконує над тим же семафором операцію А(S,1). Якщо семафора в системі не існує, будь-яка програма створює його перед виконанням операції. Оскільки при створенні семафор завжди ініціюється 0, то програма 1 може працювати без блокування тільки після запуску програми 2. Наберіть програми, збережіть під іменами 08-1а.с і 08-1b.c відповідно, відкомпілюйте і перевірте правильність їх поведінки.

Видалення набору семафорів з системи за допомогою команди ipcrm або системного виклику semctl()

Як ми бачили в прикладах, масив семафорів може продовжувати існувати в системі і після завершення процесів, що використали його, а семафори зберігатимуть своє значення. Це може привести до некоректної поведінки програм, що припускають, що семафори були тільки що створені і, отже, мають нульове значення. Необхідно видаляти семафори з системи перед запуском таких програм або перед їх завершенням. Для видалення семафорів можна скористатися командами ipcs і ipcrm, розглянутими в матеріалах попереднього семінару. Команда ipcrm в цьому випадку повинна мати вигляд

ipcrm sem <IPC ідентифікатор>

Для цієї ж мети ми можемо застосовувати системний виклик semctl(), який уміє виконувати і інші операції над масивом семафорів, але їх розгляд виходить за рамки нашого курсу.

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

#include <sys/types.h>

#include <sys/ipc.h>

#include <sys/sem.h>

int semctl(int semid, int semnum, int cmd union semun arg);

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

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

В нашому курсі ми застосовуватимемо системний виклик semctl тільки для видалення масиву семафорів з системи. Параметр semid є дескриптором System V IPC для масиву семафорів, тобто значенням, яке повернув системний виклик semget() при створенні масиву або при його пошуку по ключу.

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

Якщо які-небудь процеси знаходилися в змозі очікування для семафорів з масиву, що видаляється, при виконанні системного виклику semop(), то вони будуть розблоковані і повернуться з виклику semop() з індикацією помилки.

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

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

Поняття про POSIX-семафори

В стандарті POSIX вводяться інші семафори, повністю аналогічні семафорам Дейкстри. Для ініціалізації значення таких семафорів застосовується функція sem_init(), аналогом операції P служить функція sem_wait(), а аналогом операції V – функція sem_post(). На жаль, в Linux такі семафори реалізовані тільки для ниток виконання одного процесу, і тому детально ми на них зупинятися не будемо.

Питання до захисту роботи

  1.  Дайте визначення процесу.
  2.  Дайте визначення синхронізації процесів.
  3.  Дайте визначення памяті, що розділяється.
  4.  Дайте визначення семафору.
  5.  Які операції над семафорами входять в класичний набір, описаний Дейкстрою? В чому їх сенс?
  6.  Які операції можна здійснити з семафорами в System V IPC? В чому їх сенс?
  7.  Чи є якась відповідність між класичними операціями над семафорами та операціями над семафорами в System V IPC?
  8.  Дайте визначення поняття адресація. Які види адресації ви можете назвати? Які в них спільні та відмінні риси?
  9.  Що ви можете сказати про імена семафорів в System V IPC? Яким чином вони генеруються та зберігаються?
  10.  Чим відрізняються семафори один від одного?
  11.  Опишіть порядок роботи з кожним відомим вам різновидом семафору.
  12.  Яким чином можна отримати доступ до масиву семафорів в System V IPC? Опишіть принцип роботи відповідного системного виклику.
  13.  Які системні виклики обслуговують роботу з семафорами? Опишіть принципи їх роботи.
  14.  В чому ососбливості використання системного виклику semop()?
  15.  Поясніть, в чому полягає необхідність видалення семафорів? Як це можна здійснити?




1. . Понятие и содержание судебного доказывания.
2. CocCol Зустрічай свято Срок выполнения 1 декабря 2013 года 7 января 2014 года
3. вариант духовные люди которые напротив глубоко погрузились во внутренний мир друг друга
4.  ПАССАЖИРСКИЕ ТАРИФЫ
5. Франсуа Вийон
6. . Выбор темы и ее согласование с научным руководителем до 27
7. на тему- История английского языка
8. Синие воротнички это- индивиды занимающиеся высококвалифицированным трудом B богатые но не имеющие
9. Конспект лекций для студентов специальностей 080502 и 080109 Москва 2008 СОДЕРЖ
10. Лабораторна робота 12 Внутрішній фотоефект у напівпровідниках Мета роботи експериментально встановити