Основы программирования в Linux
Основы программирования в Linux читать книгу онлайн
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
#include <stdio.h>#include <fcntl.h>#include <errno.h>const char *lock_file = "/tmp/LCK.test2"; int main() { int file_desc; int tries = 10; while (--tries) { file_desc = open(lock_file, O_RDWR | O_CREAT | O_EXCL, 0444); if (file_desc == -1) { printf("%d - Lock already presentn", getpid()); sleep(3); } else {2. Далее следует критическая секция:
printf("%d — I have exclusive accessn", getpid()); sleep(1); (void)close(file_desc); (void)unlink(lockfile);3. В этом месте она заканчивается:
sleep(2); } } exit(EXIT_SUCCESS);}Для выполнения программы вам сначала нужно выполнить следующую команду, чтобы убедиться в том, что файла не существует:
$ <b>rm -f /tmp/LCK.test2</b>Затем с помощью приведенной далее команды запустите две копии программы:
$ <b>./lock2 & ./lock2</b>Она запускает одну копию программы в фоновом режиме, а вторую — как основную программу. Далее приведен вывод:
1284 — I have exclusive access1283 — Lock already present1283 — I have exclusive access1284 — Lock already present1284 — I have exclusive access1283 — Lock already present1283 — I have exclusive access1284 — Lock already present1284 — I have exclusive access1283 — Lock already present1283 — I have exclusive access1284 — Lock already present1284 — I have exclusive access1283 — Lock already present1283 — I have exclusive access1284 — Lock already present1284 — I have exclusive access1283 — Lock already present1283 — I have exclusive access1284 — Lock already presentВ приведенном примере показано, как взаимодействуют две выполняющиеся копии одной и той же программы. Если вы попробуете выполнить данный пример, то почти наверняка увидите другие идентификаторы процессов в выводе, но поведение программ будет тем же самым.
Как это работает
Для демонстрации вы 10 раз выполняете в программе цикл с помощью оператора
whileПоскольку это всего лишь пример, вы ждете очень короткий промежуток времени. Когда программа завершает использование ресурса, она снимает блокировку, удаляя файл с блокировкой. Далее она может выполнить другую обработку (в данном случае это просто функция
sleepВажно уяснить, что это совместное мероприятие, и вы должны корректно писать программы для его работы. Программа, потерпевшая неудачу в создании файла с блокировкой, не может просто удалить файл и попробовать снова, Возможно, в дальнейшем она сумеет создать файл с блокировкой, но у другой программы, уже создавшей такой файл, нет способа узнать о том, что она лишилась исключительного доступа к ресурсу.
Блокировка участков файла
Создание файлов с блокировкой подходит для управления исключительным доступом к ресурсам, таким как последовательные порты или редко используемые файлы, но этот способ не годится для доступа к большим совместно используемым файлам. Предположим, что у вас есть большой файл, написанный одной программой и одновременно обновляемый многими программами. Такая ситуация может возникнуть, если программа записывает какие-то данные, получаемые непрерывно или в течение длительного периода, и обрабатывает их с помощью нескольких разных программ. Обрабатывающие программы не могут ждать, пока программа, записывающая данные, завершится — она работает постоянно, поэтому программам нужен какой-то способ кооперации для обеспечения одновременного доступа к одному и тому же файлу.
Урегулировать эту ситуацию можно, блокируя участки файла. При этом конкретная часть файла блокируется, но другие программы могут иметь доступ к другим участкам файла. Это называется блокировкой сегментов или участков файла. У системы Linux есть (как минимум) два способа сделать это: с помощью системного вызова
fcntllockffcntllockffcntlfcntllockfВы встречали вызов fcntl в главе 3. У него следующее определение:
<b>#include <fcntl.h></b><b>int fcntl(int fildes, int command, ...);</b>Системный вызов
fcntlcommand
