Операционная система UNIX. Руководство программиста


Блокировка и разблокирование сегментов - часть 2


struct record { . . . /* Данные сегмента */ . . . long prev; /* Указатель на предыдущий сегмент в списке */ long next; /* Указатель на следующий сегмент в списке */ };

/* Изменение уровня блокировки с использованием fcntl(2). Предполагается, что к тому моменту, когда эта программа будет выполняться, сегменты here и next будут заблокированы на чтение. Если заблокируем на запись here и next, то: блокируем на запись сегмент this; возвращаем указатель на сегмент this. Если любая из попыток блокировки окончится неудачей, то: переустанавливаем блокировку сегментов here и next на чтение; снимаем все остальные блокировки; возвращаем -1. */

long set3lock (this, here, next) long this, here, next; { struct flock lck;

lck.l_type = F_WRLCK; /* Блокируем на запись */ lck.l_whence = 0; /* Смещение от начала будет равно l_start */ lck.l_start = here; lck.l_len = sizeof (struct record);

/* Повышение уровня блокировки сегмента here до блокировки на запись */ if (fcntl (fd, F_SETLKW, &lck) < 0) { return (-1); }

/* Блокируем сегмент this на запись */ lck.l_start = this; if (fcntl (fd, F_SETLKW, &lck) < 0) { /* Блокировка сегмента this не удалась. Понижаем блокировку сегмента here до уровня чтения */ lck.l_type = F_RDLCK; lck.l_start = here; (void) fcntl (fd, F_SETLKW, &lck); return (-1); }

/* Повышение уровня блокировки сегмента next до блокировки на запись */ lck.l_start = next; if (fcntl (fd, F_SETLKW, &lck) < 0) { /* Блокировка сегмента next не удалась. Понижаем блокировку сегмента here до уровня чтения...*/ lck.l_type = F_RDLCK; lck.l_start = here; (void) fcntl (fd, F_SETLKW, &lck); /*...и снимаем блокировку сегмента this */ lck.l_type = F_UNLCK; lck.l_start = this; (void) fcntl (fd, F_SETLKW, &lck); return (-1); /* Не смогли заблокировать */ } return (this); }

Если другие процессы мешают заблокировать нужные сегменты, то процесс перейдет в состояние ожидания, что обеспечивается операцией F_SETLKW. Если же использовать операцию F_SETLK, то в случае невозможности блокировки системный вызов fcntl(2) завершается неудчей. В последнем случае программу нужно было бы изменить для обработки подобной ситуации.




- Начало -  - Назад -  - Вперед -