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

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

Жанры

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

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

Шрифт:

17 }

18 /* запись идентификатора: файл остается открытым, чтобы он был заблокирован */

19 snprintf(line, sizeof(line), "%ld\n", (long) getpid);

20 Ftruncate(pidfd, 0);

21 Write(pidfd, line, strlen(line));

22 /* основной текст программы демона… */

23 pause;

24 }

Открытие и блокирование файла

8-17 Демон создает однострочный файл, в который записывает свой идентификатор процесса. Этот файл открывается или создается, а затем делается попытка Заблокировать его на запись целиком. Если блокировку установить не удается, мы понимаем, что один экземпляр демона уже запущен, поэтому выводится сообщение об ошибке и программа завершает работу.

ПРИМЕЧАНИЕ

Во многих версиях Unix демоны записывают свои идентификаторы в файл. Solaris 2.6 хранит подобные файлы в каталоге /etc, a Digital Unix 4.0B и BSD/OS — в каталоге /var/run.

Запись идентификатора процесса в файл

18-21 Мы укорачиваем файл до 0 байт, а затем записываем в него строку с нашим идентификатором. Причина, по которой нужно укорачивать файл, заключается в том, что у предыдущего экземпляра демона идентификатор мог быть представлен более длинным числом, чем у данного, поэтому в результате в файле может образоваться смесь двух идентификаторов.

Вот результат работы программы из листинга 9.8:

solaris % onedaemon& запускаем первый экземпляр

[1] 22388

solaris % cat pidfile проверяем идентификатор

22388

solaris % onedaemon пытаемся запустить второй экземпляр

unable to lock pidfile, is onedaemon already running?

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

9.8. Блокирование файлов

Стандарт Posix.1 гарантирует, что если функция open вызывается с флагами O_CREAT (создать файл, если он еще не существует) и O_EXCL (исключающее открытие), функция возвращает ошибку, если файл уже существует. Более того, проверка существования файла и его создание (если он еще не существует) должны представлять собой атомарную по отношению к другим процессам операцию. Следовательно, мы можем использовать создаваемый таким методом файл как блокировку. Можно быть уверенным, что только один процесс сможет создать файл (то есть получить блокировку), а для снятия этой блокировки файл можно удалить командой unlink.

В листинге 9.9 приведен текст наших функций установки и снятия блокировки, использующих этот метод. При успешном выполнении функции open мы считаем, что блокировка установлена, и успешно возвращаемся из функции my_lock. Файл мы закрываем, потому что его дескриптор нам не нужен. О наличии блокировки свидетельствует само существование файла вне зависимости от того, открыт он или нет. Если функция open возвращает ошибку EEXIST, значит, файл существует и мы должны еще раз попытаться открыть его. 

У этого метода есть три недостатка.

1. Если процесс, установивший блокировку, завершится досрочно, не сняв ее, файл не будет удален. Существуют способы борьбы с этой проблемой, например проверка времени доступа к файлу и удаление его спустя некоторый определенный промежуток времени, — но все они несовершенны. Другое решение заключается в записи в файл идентификатора процесса, чтобы другие процессы могли считать его и проверить, существует ли еще такой процесс. Этот метод также несовершенен, поскольку идентификатор может быть использован повторно.

В такой ситуации лучше пользоваться блокировкой fcntl, которая автоматически снимается по завершении процесса.

2. Если файл открыт каким-либо другим процессом, мы должны еще раз вызвать open, повторяя эти вызовы в бесконечном цикле. Это называется опросом и является напрасной тратой времени процессора. Альтернативным методом является вызов sleep на 1 секунду, а затем повторный вызов open (этапроблема обсуждалась в связи с листингом 7.4).

Эта проблема также исчезает при использовании блокировки fcntl, если использовать команду F_SETLKW. Ядро автоматически приостанавливает выполнение процесса до тех пор, пока ресурс не станет доступен.

3. Создание и удаление файла вызовом open и unlink приводит к обращению к файловой системе, что обычно занимает существенно больше времени, чем вызов fcntl (обращение производится дважды: один раз для получения блокировки, а второй — для снятия). При использовании fcntl программа выполнила 10000 повторов цикла с увеличением порядкового номера в 75 раз быстрее, чем программа, вызывавшая open и unlink.

Листинг 9.9. Функции блокировки с использованием open с флагами O_CREAT и O_EXCL

//lock/lockopen.c

1 #include "unpipc.h"

2 #define LOCKFILE "/tmp/seqno.lock"

3 void

4 my_lock(int fd)

5 {

6 int tempfd;

7 while ((tempfd = open(LOCKFILE, O_RDWR|O_CREAT|O_EXCL, FILE_MODE)) < 0) {

8 if (errno != EEXIST)

9 err_sys("open error for lock file");

10 /* блокировка установлена кем-то другим, повторяем попытку */

11 }

12 Close(tempfd); /* открыли файл, блокировка установлена */

13 }

14 void

15 my_unlock(int fd)

16 {

17 Unlink(LOCKFILE); /* снимаем блокировку удалением файла */

18 }

Есть еще две особенности файловой системы Unix, которые использовались для реализации блокировок. Первая заключается в том, что функция link возвращает ошибку, если имя новой ссылки уже существует. Для получения блокировки создается уникальный временный файл, полное имя которого содержит в себе его идентификатор процесса (или комбинацию идентификаторов процесса и потока, если требуется осуществлять блокировку между отдельными потоками). Затем вызывается функция link для создания ссылки на этот файл с каким-либо определенным заранее именем. После успешного создания сам файл может быть удален вызовом unlink. После осуществления работы с блокировкой файл с известным именем удаляется командой unlink. Если link возвращает ошибку EEXIST, поток должен попытаться создать ссылку еще раз (аналогично листингу 9.9). Одно из требований к этому методу — необходимо, чтобы и временный файл, и ссылка находились в одной файловой системе, поскольку большинство версий Unix не допускают создания жестких ссылок (результат вызова link) в разных файловых системах.

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

Маска зверя

Метельский Николай Александрович
6. Унесенный ветром
Фантастика:
боевая фантастика
8.20
рейтинг книги
Маска зверя

Второгодка. Книга 4. Подавать холодным

Ромов Дмитрий
4. Второгодка
Фантастика:
героическая фантастика
альтернативная история
сказочная фантастика
5.00
рейтинг книги
Второгодка. Книга 4. Подавать холодным

Магия чистых душ

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.40
рейтинг книги
Магия чистых душ

Гроза богов

Мазуров Дмитрий
10. Громовая поступь
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Гроза богов

Старый, но крепкий 2

Крынов Макс
2. Культивация без насилия
Фантастика:
рпг
уся
эпическая фантастика
5.00
рейтинг книги
Старый, но крепкий 2

Забытые боги

Рокотов Алексей
4. Путь князя
Фантастика:
фэнтези
рпг
попаданцы
5.00
рейтинг книги
Забытые боги

Охотник за головами

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

Солдат Империи

Земляной Андрей Борисович
1. Страж
Фантастика:
попаданцы
альтернативная история
6.67
рейтинг книги
Солдат Империи

Прапорщик. Назад в СССР. Книга 7

Гаусс Максим
7. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прапорщик. Назад в СССР. Книга 7

Травник

Назимов Константин Геннадьевич
1. Травник
Фантастика:
фэнтези
5.00
рейтинг книги
Травник

Сильнейший Столп Империи. Книга 3

Ермоленков Алексей
3. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 3

Он тебя не любит(?)

Тоцка Тала
Любовные романы:
современные любовные романы
7.46
рейтинг книги
Он тебя не любит(?)

Я князь. Книга XVIII

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

Источники силы

Amazerak
4. Иной в голове
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Источники силы