Чтение онлайн

на главную - закладки

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

1. Считать порядковый номер из файла.

2. Использовать этот номер.

3. Увеличить его на единицу и записать обратно в файл.

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

ПРИМЕЧАНИЕ

Описанная выше проблема называется проблемой взаимных исключений. Она может быть решена с использованием взаимных исключений из главы 7 или блокировок чтения-записи из главы 8. Различие состоит в том, что здесь мы предполагаем неродственность процессов, что усложняет использование предложенных выше методов. Мы могли бы использовать разделяемую память (подробно об этом говорится в четвертой части книги), поместив в нее переменную синхронизации одного из этих типов, но для неродственных процессов проще воспользоваться блокировкой fcntl. Другим фактором в данном случае стало то, что проблема со спулерами печати возникла задолго до появления взаимных исключений, условных переменных и блокировок чтения-записи. Блокировка записей была добавлена в Unix в начале 80-х, до того как появились концепции разделяемой памяти и программных потоков.

Таким образом, процессу нужно заблокировать файл, чтобы никакой другой процесс не мог получить к нему доступ, пока первый выполняет свои три действия. В листинге 9.2 приведен текст простой программы, выполняющей соответствующие действия. Функции my_lock и my_unlock обеспечивают блокирование и разблокирование файла в соответствующие моменты. Мы приведем несколько возможных вариантов реализации этих функций.

20 Каждый раз при прохождении цикла мы выводим имя программы (argv[0]) перед порядковым номером, поскольку эта функция main будет использоваться с различными версиями функций блокировки и нам бы хотелось видеть, какая версия программы выводит данную последовательность порядковых номеров.

ПРИМЕЧАНИЕ

Вывод идентификатора процесса требует преобразования переменной типа pid_t к типу long и последующего использования строки формата %ld. Проблема тут в том, что идентификатор процесса принадлежит к одному из целых типов, но мы не знаем, к какому именно, поэтому предполагается наиболее вместительный — long. Если бы мы предположили, что идентификатор имеет тип int и использовали бы строку %d, a pid_t на самом деле являлся бы типом long, код мог бы работать неправильно.

Посмотрим, что будет, если не использовать блокировку. В листинге 9.1 [1] приведены версии функций my_lock и my_unlock, которые вообще ничего не делают.

Листинг 9.1. Функции, не осуществляющие блокировку

//lock/locknone.c

1 void

2 my_lock(int fd)

3 {

4 return;

5 }

6 void

7 my_unlock(int fd)

1

Все исходные тексты, опубликованные в этой книге, вы можете найти по адресу http://www.piter.com/download.

8 {

9 return;

10 }

Листинг 9.2. Функция main для примеров с блокировкой файла

//lock/lockmain.c

1 #include "unpipc.h"

2 #define SEQFILE "seqno" /* имя файла */

3 void my_lock(int), my_unlock(int);

4 int

5 main(int argc, char **argv)

6 {

7 int fd;

8 long i, seqno;

9 pid_t pid;

10 ssize_t n;

11 char line[MAXLINE + 1];

12 pid = getpid;

13 fd = Open(SEQFILE, O_RDWR, FILE_MODE);

14 for (i = 0; i < 20; i++) {

15 my_lock(fd); /* блокируем файл */

16 Lseek(fd, 0L, SEEK_SET); /* переходим к его началу */

17 n = Read(fd, line, MAXLINE);

18 line[n] = '\0'; /* завершающий 0 для sscanf */

19 n = sscanf(line, "%ld\n", &seqno);

20 printf(%s; pid = %ld, seq# = %ld\n", argv[0], (long) pid, seqno);

21 seqno++; /* увеличиваем порядковый номер */

22 snprintf(line, sizeof(line), "%ld\n", seqno);

23 Lseek(fd, 0L, SEEK_SET); /* переходим на начало перед записью */

24 Write(fd, line, strlen(line));

25 my_unlock(fd); /* разблокируем файл */

26 }

27 exit(0);

28 }

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

solaris % locknone

locknone: pid = 15491, seq# = 1

locknone: pid = 15491, seq# = 2

locknone: pid = 15491, seq# = 3

locknone: pid = 15491, seq# = 4

locknone: pid = 15491. seq# = 5

locknone: pid = 15491, seq# = 6

locknone: pid = 15491, seq# = 7

locknone: pid = 15491, seq# – 8

locknone: pid = 15491, seq# = 9

locknone: pid = 15491, seq# = 10

locknone: pid = 15491, seq# = 11

locknone: pid = 15491, seq# = 12

locknone: pid = 15491, seq# = 13

locknone: pid = 15491, seq# = 14

locknone: pid = 15491, seq# = 15

locknone: pid = 15491, seq# = 16

locknone: pid = 15491, seq# = 17

locknone: pid = 15491, seq# = 18

locknone: pid = 15491, seq# = 19

locknone: pid = 15491, seq# = 20

ПРИМЕЧАНИЕ

Обратите внимание, что функция main хранится в файле lockmain.c, но мы компилируем и компонуем эту программу с функциями, не осуществляющими никакой блокировки (листинг 9.1), поэтому мы называем ее locknone. Ниже будут использоваться другие версии функций my_lock и my_unlock, и исполняемый файл будет называться по-другому в соответствии с используемым методом блокировки.

Поделиться:
Популярные книги

Кодекс Охотника. Книга XXXV

Винокуров Юрий
35. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXV

Наследие Маозари 6

Панежин Евгений
6. Наследие Маозари
Фантастика:
попаданцы
постапокалипсис
рпг
фэнтези
эпическая фантастика
5.00
рейтинг книги
Наследие Маозари 6

Газлайтер. Том 29

Володин Григорий Григорьевич
29. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 29

Бастард

Майерс Александр
1. Династия
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Бастард

Я – Легенда 2: геном хищника

Гарцевич Евгений Александрович
2. Я - Легенда!
Фантастика:
боевая фантастика
рпг
фантастика: прочее
попаданцы
5.00
рейтинг книги
Я – Легенда 2: геном хищника

Газлайтер. Том 19

Володин Григорий Григорьевич
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 19

Поход

Валериев Игорь
4. Ермак
Фантастика:
боевая фантастика
альтернативная история
6.25
рейтинг книги
Поход

Технарь

Муравьёв Константин Николаевич
1. Технарь
Фантастика:
космическая фантастика
попаданцы
7.13
рейтинг книги
Технарь

Я снова князь. Книга XXIII

Дрейк Сириус
23. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я снова князь. Книга XXIII

Горизонт Вечности

Вайс Александр
11. Фронтир
Фантастика:
боевая фантастика
космическая фантастика
космоопера
5.00
рейтинг книги
Горизонт Вечности

Кодекс Охотника. Книга XXXVI

Винокуров Юрий
36. Кодекс Охотника
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Кодекс Охотника. Книга XXXVI

Фантом памяти

Маринина Александра
2. Преступления правильной жизни
Детективы:
прочие детективы
8.43
рейтинг книги
Фантом памяти

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Идеальный мир для Лекаря 28

Сапфир Олег
28. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 28