Читаем Linux API. Исчерпывающее руководство полностью

Аргумент cmd поддерживает значения g (F_GETLK), s (F_SETLK) или w (F_SETLKW). Остальные аргументы применяются для инициализации структуры flock, передаваемой в вызов fcntl(). Аргумент lock представляет собой значение поля l_type и может быть равен r (F_RDLCK), w (F_WRLCK) или u (F_WRLCK). Аргументы start и length являются целыми числами, представляющими значения полей l_start и l_len. Последний аргумент, whence, является необязательным и представляет значение поля l_whence; он может быть равен s (SEEK_SET — по умолчанию), c (SEEK_CUR) или e (SEEK_END). Причина, по которой мы приводим поля l_start и l_len к типу long long, когда передаем их в вызов printf(), описана в разделе 5.10.

Листинг 51.2. Эксперимент с блокировкой записей

filelock/i_fcntl_locking.c

#include

#include

#include "tlpi_hdr.h"

#define MAX_LINE 100

static void

displayCmdFmt(void)

{

printf("\n Format: cmd lock start length [whence]\n\n");

printf(" 'cmd' is 'g' (GETLK), 's' (SETLK), or 'w' (SETLKW)\n");

printf(" 'lock' is 'r' (READ), 'w' (WRITE), or 'u' (UNLOCK)\n");

printf(" 'start' and 'length' specify byte range to lock\n");

printf(" 'whence' is 's' (SEEK_SET, default), 'c' (SEEK_CUR), "

"or 'e' (SEEK_END)\n\n");

}

int

main(int argc, char *argv[])

{

int fd, numRead, cmd, status;

char lock, cmdCh, whence, line[MAX_LINE];

struct flock fl;

long long len, st;

if (argc!= 2 || strcmp(argv[1], "-help") == 0)

usageErr("%s file\n", argv[0]);

fd = open(argv[1], O_RDWR);

if (fd == -1)

errExit("open (%s)", argv[1]);

printf("Enter? for help\n");

for (;;) { /* Просим ввести команду блокирования и выполняем ее */

printf("PID=%ld> ", (long) getpid());

fflush(stdout);

if (fgets(line, MAX_LINE, stdin) == NULL) /* Конец файла */

exit(EXIT_SUCCESS);

line[strlen(line) — 1] = '\0'; /* Удаляем '\n' в конце */

if (*line == '\0')

continue; /* Пропускаем пустые строки */

if (line[0] == '?') {

displayCmdFmt();

continue;

}

whence = 's'; /* Значение по умолчанию для 'whence' */

numRead = sscanf(line, "%c %c %lld %lld %c", &cmdCh, &lock,

&st, &len, &whence);

fl.l_start = st;

fl.l_len = len;

if (numRead < 4 || strchr("gsw", cmdCh) == NULL ||

strchr("rwu", lock) == NULL || strchr("sce", whence) == NULL) {

printf("Invalid command!\n");

continue;

}

cmd = (cmdCh == 'g')? F_GETLK: (cmdCh == 's')

? F_SETLK: F_SETLKW;

fl.l_type = (lock == 'r')? F_RDLCK: (lock == 'w')

? F_WRLCK: F_UNLCK;

fl.l_whence = (whence == 'c')? SEEK_CUR:

(whence == 'e')? SEEK_END: SEEK_SET;

status = fcntl(fd, cmd, &fl); /* Выполняем запрос… */

if (cmd == F_GETLK) { /*…и смотрим, что получилось */

if (status == -1) {

errMsg("fcntl — F_GETLK");

} else {

if (fl.l_type == F_UNLCK)

printf("[PID=%ld] Lock can be placed\n",

(long) getpid());

else /* Заблокировано кем-то другим */

printf("[PID=%ld] Denied by %s lock on %lld:%lld "

"(held by PID %ld)\n", (long) getpid(),

(fl.l_type == F_RDLCK)? "READ": "WRITE",

(long long) fl.l_start,

(long long) fl.l_len, (long) fl.l_pid);

}

} else { /* F_SETLK, F_SETLKW */

if (status == 0)

printf("[PID=%ld] %s\n", (long) getpid(),

(lock == 'u')? "unlocked": "got lock");

else if (errno == EAGAIN || errno == EACCES) /* F_SETLK */

printf("[PID=%ld] failed (incompatible lock)\n",

(long) getpid());

else if (errno == EDEADLK) /* F_SETLKW */

printf("[PID=%ld] failed (deadlock)\n", (long) getpid());

else

errMsg("fcntl — F_SETLK(W)");

}

}

}

filelock/i_fcntl_locking.c

В сессиях командной строки, представленных ниже, демонстрируется использование двух экземпляров программы из листинга 51.2, с помощью которых устанавливаются блокировки для одного и того же файла размером 100 байт (tfile). На рис. 51.5 показано состояние удовлетворенных и отложенных запросов на получение блокировки на разных этапах сессии (см. комментарии ниже).

Для начала запустим первый экземпляр программы из листинга 51.2 (процесс А), установив блокировку для чтения байтов файла с 0 по 39:

Terminal window 1

$ ls — l tfile

— rw-r-r- 1 mtk users 100 Apr 18 12:19 tfile

$ ./i_fcntl_locking tfile

Enter? for help

PID=790> s r 0 40

[PID=790] got lock

Теперь запустим второй экземпляр программы (процесс Б) и установим блокировку для чтения байтов с 70 и до конца файла:

Terminal window 2

$ ./i_fcntl_locking tfile

Enter? for help

PID=800> s r -30 0 e

[PID=800] got lock

К этому моменту все должно выглядеть так, как на рис. 51.5, а, где процессы А (ID процесса — 790) и Б (ID процесса — 800) удерживают блокировки для разных участков файла.

Теперь мы возвращаемся к процессу A, где пытаемся добавить блокировку с возможностью записи для всего файла. Сначала мы используем операцию F_GETLK для проверки того, можно ли убрать блокировку и выдать сообщение, что существует конфликтная блокировка. Затем мы пытаемся установить блокировку с помощью операции F_SETLK, которая также не работает. Наконец, мы пытаемся добавить блокировку с F_SETLKW.

PID=790> g w 0 0

[PID=790] Denied by READ lock on 70:0 (held by PID 800)

PID=790> s w 0 0

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных