Читаем Основы программирования в Linux полностью

В программе lock1.c вы сможете увидеть файл с блокировкой в действии.

#include 

#include 

#include 

#include 

#include 

int main {

 int file_desc;

 int save_errno;

 file_desc = open("/tmp/LCK.test", O_RDWR | O_CREAT | O_EXCL, 0444);

 if (file_desc == -1) {

  save errno = errno;

  printf("Open failed with error %d\n", save_errno);

 } else {

  printf("Open succeeded\n");

 }

 exit(EXIT_SUCCESS);

} 

Выполнив программу первый раз, вы получите следующий вывод:

./lock1

Open succeeded

Но при повторной попытке вы получите результат, приведенный далее:

$ ./lock1

Open failed with error 17

Как это работает

Для создания файла с именем /tmp/LCK.test программа выполняет вызов, использующий флаги O_CREAT и O_EXCL. Во время первого выполнения программы файл не существует, поэтому вызов open завершается успешно. Последующие запуски программы завершаются аварийно, потому что файл уже существует. Для успешного выполнения этой программы в дальнейшем вы должны вручную удалить файл с блокировкой.

В системах Linux, ошибка 17 соответствует константе EEXIST, указывающей на то, что файл уже существует. Номера ошибок определены в файле errno.h или, скорее, в файлах, включаемых этим файлом. В данном случае определение в действительности, находящееся в /usr/include/asm-generic/errno-base.h, гласит

#define EEXIST 17 /* File exists */

Это ошибка, соответствующая аварийному завершению вызова open(O_CREAT | O_EXCL).

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

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

Упражнение 7.8. Совместная блокировка файлов

1. Далее приведен исходный код тестовой программы lock2.с.

#include

#include  

#include

#include

#include

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 present\n", getpid);

   sleep(3);

  } else {

2. Далее следует критическая секция:

   printf("%d — I have exclusive access\n", getpid);

   sleep(1);

   (void)close(file_desc);

   (void)unlink(lockfile);

3. В этом месте она заканчивается:

   sleep(2);

  }

 }

 exit(EXIT_SUCCESS);

}

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

$ rm -f /tmp/LCK.test2

Затем с помощью приведенной далее команды запустите две копии программы:

$ ./lock2 & ./lock2

Она запускает одну копию программы в фоновом режиме, а вторую — как основную программу. Далее приведен вывод:

1284 — I have exclusive access

1283 — Lock already present

1283 — I have exclusive access

1284 — Lock already present

1284 — I have exclusive access

1283 — Lock already present

1283 — I have exclusive access

1284 — Lock already present

1284 — I have exclusive access

1283 — Lock already present

1283 — I have exclusive access

1284 — Lock already present

1284 — I have exclusive access

1283 — Lock already present

1283 — I have exclusive access

1284 — Lock already present

1284 — I have exclusive access

1283 — Lock already present

Перейти на страницу:
Нет соединения с сервером, попробуйте зайти чуть позже