Приклад блокування на читання за наявності у черзі блокування на запис

Приклад: блокування на читання за наявності у черзі блокування на запис

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

Щоб перевірити, як ця ситуація вирішиться при використанні блокування записів fcntl, напишемо тестову програму, яка встановлює блокування читання для всього файлу і потім породжує два процеси за допомогою fork.

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

Мал. 9.2. Визначення можливості встановлення блокування на читання за наявностів черги блокування на запис

Лістинг 9.6. Визначення можливості встановлення блокування на читання за наявності у черзі блокування на запис

//lock/test2.c 1 #include "unpipc.h" 2 int 3 main(int argc, char **argv) 4 5 int fd; 6 fd = Open("test1.data", O_RDWR O_CREAT, FILE_MODE); 7 Read_lock(fd, 0, SEEK_SET, 0); /* батьківський процес блокує весь файл для читання */ 8 printf("%s: parent has read lockn", Gf_time()); 9 if (Fork() == 0) 10 /* перший дочірній процес */ 11сон(1); 12 printf("%s: перша дитина намагається отримати блокування запису", Gf_time()); 13 Writew_lock(fd, 0, SEEK_SET, 0); /* тут він буде заблокований */ 14 printf("%s: перша дитина отримує блокування запису", Gf_time()); 15 сон (2); 16 Un_lock(fd, 0, SEEK_SET, 0); 17 printf("ls: перша дочірня програма випускає запис lockn", Gf_time()); 18 вихід (0); 19 > 20 if (Fork() == 0) 21 /* другий дочерний процес */ 22 sleep(3); 23 printf("%s: друга дитина намагається отримати блокування читання", Gf_time()); 24 Readw_lock(fd, 0, SEEK_SET, 0); 25 printf("%s: друга дитина отримує блокування читання", Gf_time()); 26 сон (4); 27 Un_lock(fd, 0, SEEK_SET, 0); 28 printf("%s: другий дочірній елемент випускає блокування читання", Gf_time()); 29 вихід (0); 30 > 31 /* батьківський процес */ 32 sleep(5); 33 Un_lock(fd, 0, SEEK_SET, 0); 34 printf("%s: батьківський реліз читає lockn", Gf_time()); 35 вихід (0); 36 >

Родительский процес відкриває файл і отримує блокировку на чтение

6-8 Родительський процес відкриває файл і встановлює блокування на чтенні для всього цілого файлу. Зверніть увагу, що ми викликаємо read_lock (котора повертає помилку в разі недоступності ресурсу), а не readw_lock (яка очікує його звільнення), тому що ми очікуємо, що ця блокування буде встановлена ​​негайно. Ми також виводимо значення поточного часу функцією gf_time [24, с. 404], коли отримуємо блокування.

Перший дочерний процес

9-19 Відбувається перший процес, який чекає 1 секунду і блокується в очікуванні отримання блокування на запис для всього файлу. Потім він встановлює цю блокировку, чекає 2 секунди, знімає її і завершує роботу.

Второй дочерний процес

20-30 Порождається другий процес, який чекає 3 секунди, даєтьсяможливість першому спробувати встановити блокування на запис, а потім намагається отримати блокування читання для всього файлу. На момент повернення з функції readw_lock ми можемо дізнатися, чи був ресурс наданий негайно, чи другого процесу довелося чекати першого. Блокування знімається за чотири секунди.

Батьківський процес блокує ресурс 5 секунд

31-35 Батьківський процес чекає на п'ять секунд, знімає блокування і завершує роботу.

На рис. 9.2 наведено часову діаграму виконання програми в Solaris 2.6, Digital Unix 4.0B та BSD/OS 3.1. Як видно, блокування читання надається другому дочірньому процесу негайно, незважаючи на наявність у черзі запиту на блокування запису. Існує ймовірність, що запит на запис так і не буде виконаний, якщо постійно надходитимуть нові запити на читання. Нижче наведено результат виконання програми, до якого були додані порожні рядки для покращення читаності:

alpha %test2 16:32:29.674453: parent has read lock 16:32:30.709197: перша дитина tries to obtain write lock to obtain read lock 16:32:32.728739: second child obtains read lock 16:32:34.722282: parent releases read lock 16:32:36.729738: second child relees 32:36.735597: first child obtains write lock 16:32:38.736938: first child releases write lock