В программе 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)
.
Если программе на короткий период во время выполнения, часто называемыйunlink
для удаления этого файла впоследствии, когда она завершит выполнение критической секции.
Вы можете увидеть сотрудничество программ, применяющих этот механизм блокировки, написав программу-пример и запустив одновременно две ее копии (упражнение 7.8). В программе будет использован вызов функции getpid
, с которой вы встречались в
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