Основы программирования в Linux
На рис. 7.1 показан этот сценарий с блокировками в тот момент, когда программа переходит к ожиданию.
Рис. 7.1
Сама по себе эта программа не очень полезна. Вам нужна вторая программа lock4.c для тестирования блокировок (упражнение 7.10).
Упражнение 7.10. Тестирование блокировок файлаВ этом примере вы напишете программу, проверяющую блокировки разных типов, установленные для различных участков файла.
1. Как обычно, начнем с заголовочных файлов и объявлений:
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <fcntl.h>const char *test_file = "/tmp/test_lock";#define SIZE_TO_TRY 5void show_lock_info(struct flock *to_show);int main() {int file_desc;int res;struct flock region_to_test;int start_byte;2. Откройте дескриптор файла:
file_desc = open(test_file, O_RDWR | O_CREAT, 0666);if (!file_desc) {fprintf(stderr, "Unable to open %s for read/write", test_file);exit(EXIT_FAILURE);}for (start_byte = 0; start_byte < 99; start_byte += SIZE_TO_TRY) {3. Задайте участок файла, который хотите проверить:
region_to_test.l_type = F_WRLCK;region_to_test.l_whence = SEEK_SET;region_to_test.lstart = start_byte;region_to_test.l_len = SIZE_TO_TRY;region_to_test.l_pid = -1;printf("Testing F_WRLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY);4. Теперь проверьте блокировку файла:
res = fcntl(file_desc, F_GETLK, &region_to_test);if (res == -1) {fprintf(stderr, "F_GETLK failed\n");exit(EXIT_FAILURE);}if (region_to_test.l_pid != -1) {printf("Lock would fail. F_GETLK returned:\n");showlockinfo(&region_to_test);} else {printf("F_WRLCK - Lock would succeed\n");}5. Далее повторите тест с разделяемой блокировкой (на чтение). Снова задайте участок файла, который хотите проверить:
region_to_test.l_type = F_RDLCK;region_to_test.l_whence = SEEK_SET;region_to_test.l_start = start_byte;region_to_test.l_len = SIZE_TO_TRY;region_to_test.l_pid = -1;printf("Testing F_RDLCK on region from %d to %d\n", start_byte, start_byte + SIZE_TO_TRY);6. Еще раз проверьте блокировку файла:
res = fcntl(file_desc, F_GETLK, &region_to_test);if (res == -1) {fprintf(stderr, "F_GETLK failed\n");exit(EXIT_FAILURE);}if (region_to_test.l_pid != -1) {printf("Lock would fail. F_GETLK returned:\n");show_lock_info(&region_to_test);} else {printf("F_RDLCK — Lock would succeed\n");}}close(file_desc);exit(EXIT_SUCCESS);}void show_lock_info(struct flock *to_show) {printf("\tl_type %d, ", to_show->l_type);printf("l_whence %d, ", to_show->l_whence);printf("l_start %d, (int)to_show->l_start);printf("l_len %d, ", (int)to_show->l_len);printf("l_pid %d\n", to_show->l_pid);}Для проверки блокировки сначала запустите программу lock3, затем выполните программу lock4, чтобы протестировать заблокированный файл. Сделайте это, запустив программу lock3 в фоновом режиме с помощью следующей команды:
$ <b>./lock3 &</b>$ process 1534 locking fileНа экране появится приглашение для ввода команд, поскольку lock3 выполняется в фоновом режиме. Далее сразу же запустите программу lock4 с помощью следующей команды:
$ <b>./lock4</b>Вы получите вывод, приведенный далее с некоторыми пропусками для краткости:
Testing F_WRLCK on region from 0 to 5F_WRLCK — Lock would succeedTesting F_RDLCK on region from 0 to 5F_RDLCK - Lock would succeed...Testing F_WRLCK on region from 10 to 15Lock would fail. F_GETLK returned:l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 1534Testing F_RDLCK on region from 10 to 15F_RDLCK — Lock would succeedTesting F_WRLCK on region from 15 to 20Lock would fail. F_GETLK returned:
