КаталогИндекс раздела
НазадОглавлениеВперед


Блокировка файлов и сегментов

СОДЕРЖАНИЕ

1. Введение

2. Терминология

3. Блокировка файлов и сегментов
    3.1. Открытие файлов для блокировки сегментов
    3.2. Блокировка файлов
    3.3. Блокировка и разблокирование сегментов
    3.4. Получение информации о блокировке
    3.5. Управление тупиковыми ситуациями

4. Выбор слабой или сильной блокировки
    4.1. Сильная блокировка. Некоторые предупреждения
    4.2. Блокировка сегментов и развитие системы UNIX


1. ВВЕДЕНИЕ

В текущей версии системы UNIX реализованы два вида блокировки сегментов и файлов: слабая и сильная. Назначение этих средств - дать возможность программам, одновременно обрабатывающим одни и те же данные, синхронизировать свою работу. Поскольку подобный режим обработки данных характерен для многопользовательских приложений, необходимость общего решения проблемы синхронизации признана такими авторитетными в области стандартов организациями, как /usr/group, которая объединяет многочисленных пользователей системы UNIX во многих странах.

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

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

В связи с тем, что ниже содержатся ссылки на описания системного вызова fcntl(2), библиотечной функции lockf(3C), а также на команды и структуры данных fcntl(5), Вам, прежде чем продолжать чтение, следует ознакомиться с соответствующими разделами Справочника программиста.

 

2. ТЕРМИНОЛОГИЯ

Прежде чем перейти к описанию средств блокировки сегментов, определим некоторые термины.

Сегмент
  Последовательный участок файла. Операционная система UNIX не поддерживает структуру сегментов файла. Если это нужно, Вы должны делать это сами в программах, работающих с файлами.
Взаимодействующие процессы
  Процессы, которые работают совместно для достижения некоторой заранее определенной общей цели. Процессы, совместно использующие файлы, должны запрашивать разрешение на доступ к файлу перед его использованием. Права доступа должны быть правильно установлены, чтобы не дать возможности доступа к этим файлам из других процессов. Термин процесс далее неизменно будет применяться в отношении процессов такого рода.
Блокировка на чтение (разделяемая)
  Используется для того, чтобы установить ограниченный доступ к сегментам файла. Когда сегмент заблокирован на чтение, другие процессы также могут заблокировать на чтение весь сегмент или его часть. Никакие другие процессы, однако, не должны (к моменту блокировки на чтение) блокировать на запись пересекающийся с сегментом участок файла, и не смогут сделать это позже. Если процесс заблокировал сегмент на чтение, то можно считать, что никакие процессы не будут записывать или изменять этот сегмент в то же самое время. Тем не менее данный способ блокировки позволяет многим процессам читать данный сегмент одновременно. Такая блокировка необходима, например, когда организуется поиск в файле, а запросы на блокировку на запись (монопольную) могут привести к нежелательным осложнениям.
Блокировка на запись (монопольная)
  Используется для получения полного контроля над доступом к сегменту файла. Когда сегмент блокируется монопольно, никакие другие процессы не имеют возможности заблокировать на чтение или запись весь сегмент или его часть. Если процесс заблокировал сегмент на запись, можно считать, что никакие процессы не будут записывать или читать данный сегмент в это же самое время.
Слабая блокировка
  Данная форма блокировки сегментов не взаимодействует с подсистемой ввода-вывода [то есть с системными вызовами creat(2), open(2), read(2) и write(2)]. Контроль над сегментом устанавливается запросом на соответствующую блокировку, выдаваемым до операций ввода-вывода. Если соответствующие запросы делают все процессы, обрабатывающие файл, доступ к файлу будет управляться взаимодействием этих запросов. Слабая блокировка обеспечивает выполнение протокола блокировки сегментов для всех использующих ее процессов; она не означает дополнительных проверок доступности во время любого запроса на ввод-вывод.
Сильная блокировка
  Данная форма блокировки сегментов взаимодействует с подсистемой ввода-вывода. Контроль блокировки сегментов осуществляется системными вызовами creat(2), open(2), read(2) и write(2). Если сегмент заблокирован, то доступ к нему со стороны других процессов ограничивается в соответствии с типом блокировки. Управление блокировкой по-прежнему должно осуществляться путем явной выдачи соответствующего запроса на нее перед операциями ввода-вывода, однако перед каждой операцией ввода-вывода системой будут делаться дополнительные проверки, чтобы обеспечить выполнение протокола блокировки сегментов. Сильная блокировка обеспечивает дополнительный контроль очередности обращений к данным за счет некоторой потери эффективности.

3. БЛОКИРОВКА ФАЙЛОВ И СЕГМЕНТОВ

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

Только заранее определенное множество программ и/или пользователей должно иметь возможность читать или записывать в базу данных (файл). Указанной цели можно легко достичь, если взвести бит переустановки идентификатора группы [см. chmod(1)] для программ, работающих с базой данных. После этого только определенное множество программ, поддерживающих протокол блокировки сегментов, смогут иметь доступ к файлам. Примером подобной защиты файлов является утилита mail(1), хотя в данном случае блокировка сегментов не используется. Порождаемые этой утилитой файлы непрочитанных писем могут читать и изменять только адресаты и сама команда mail(1).

3.1. Открытие файлов для блокировки сегментов

Первое требование для блокировки файла или сегмента файла состоит в том, чтобы иметь корректный дескриптор файла. Если будет устанавливаться блокировка на чтение, файл должен быть открыт как минимум на чтение. Соответственно, для блокировки на запись необходим доступ на запись. В следующем примере файл открывается как на чтение, так и на запись.

       #include <stdio.h>
       #include <errno.h>
       #include <fcntl.h>
       
       int fd;  /* дескриптор файла */
       char *filename;
       
       main (argc, argv)
       int argc;
       char *argv [];
       {
         extern void exit (), perror ();

         /* Получение имени файла базы данных из командной строки
            и открытие файла на чтение и запись. */
       
         if (argc < 2) {
           (void) fprintf (stderr, "Usage: %s file\n", argv[0]);
           exit (2);
         }
         filename = argv [1];
         fd = open (filename, O_RDWR);
         if (fd < 0) {
           perror (filename);
           exit (2);
         }
          . . .

Теперь файл открыт для выполнения как блокировок, так и функций ввода-вывода. Попробуем теперь установить блокировку.

3.2. Блокировка файлов

Есть несколько способов блокировки файла. Конкретный выбор зависит, в частности, от того, как оставшаяся часть программы будет использовать блокировку. Нужно также учесть проблемы эффективности и мобильности программы. Далее будут описаны два метода: один использует системный вызов fcntl(2), другой - библиотечную функцию lockf(3C) (удовлетворяющую стандарту /usr/group).

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

       #include <fcntl.h>
          . . .
       #define MAX_TRY 10
       int try;
       struct flock lck;
       
       try = 0;

       /* Заполним структуру, нужную для блокировки сегмента.
          Адрес структуры передается системному вызову fcntl */
       
       lck.l_type = F_WRLCK; /* Блокировка на запись */
       lck.l_whence = 0; /* Смещение от начала будет равно l_start */
       lck.l_start = 0L; /* Блокировка от начала файла */
       lck.l_len = 0L; /* и до конца */

       /* Делаем не более MAX_TRY попыток блокировки */
       
       while (fcntl (fd, F_SETLK, &lck) < 0) {
         if (errno == EAGAIN || errno == EACCES) {
         /* Могут быть и другие ошибки, при которых
            надо повторить попытку */
           if (++try < MAX_TRY) {
             (void) sleep (2);
             continue;
           }
           (void) fprintf (stderr, "Файл занят\n");
           return;
         }
         perror("fcntl");
         exit(2);
       }
          . . .

Приведенная часть исходного текста пытается заблокировать файл. Попытки повторяются несколько раз до тех пор, пока не случится одно из событий:

Чтобы выполнить эту же задачу, используя функцию lockf(3C), исходный текст должен иметь следующий вид:

       #include <unistd.h>
       #define MAX_TRY 10
       int try;
       try = 0;

       /* Устанавливаем указатель текущей позиции в начало файла */
       
       lseek (fd, 0L, 0);
       
       /* Делаем не более MAX_TRY попыток блокировки */
       
       while (lockf (fd, F_TLOCK, 0L) < 0) {
         if (errno == EAGAIN || errno == EACCES) {
         /* Могут быть и другие ошибки, при которых
            надо повторить попытку */
           if (++try < MAX_TRY) {
             (void) sleep (2);
             continue;
           }
           (void) fprintf (stderr, "Файл занят\n");
           return;
         }
         perror("lockf");
         exit(2);
       }
          . . .

Надо заметить, что пример с использованием lockf(3C) выглядит проще, однако пример с fcntl(2) демонстрирует дополнительную гибкость. При использовании fcntl(2) можно установить тип блокировки и начало блокируемого сегмента просто путем присваивания нужных значений компонентам структуры. В случае lockf(3C) просто устанавливается блокировка на запись (монопольная); для того, чтобы указать начало блокируемого сегмента, нужен дополнительный системный вызов [lseek(2)].

3.3. Блокировка и разблокирование сегментов

Блокировка сегментов осуществляется практически тем же способом, что и блокировка файлов. Различие состоит только в начальной точке и длине блокируемого участка. Далее мы рассмотрим интересную и практически важную задачу. Есть два сегмента (в одном или двух файлах), которые должны быть изменены одновременно таким образом, чтобы другие процессы не могли получить доступ к промежуточному состоянию изменяемой информации. (Подобные задачи встречаются, например, при необходимости изменить указатели в двунаправленных списках.) Чтобы решить нашу задачу, необходимо ответить на следующие вопросы:

При управлении блокировкой сегментов мы должны планировать свои действия на случай неудачной попытки блокировки. Эти действия в первую очередь зависят от характера информации, хранящейся в тех сегментах, которые мы пытаемся блокировать. Возможны, например, следующие действия:

Теперь рассмотрим пример включения элемента в двунаправленный список. Допустим, что сегмент, после которого мы хотим включить новый элемент, уже заблокирован на чтение. Чтобы этот сегмент можно было корректировать, блокировка должна быть снята и уста- новлена снова или ее уровень повышен до блокировки на запись.

Повышение уровня блокировки (обычно от блокировки на чтение до блокировки на запись) разрешается в том случае, если нет других процессов, заблокировавших на чтение ту же часть файла. Наличие процессов, ожидающих возможности заблокировать на запись ту же часть файла, не мешает повышению уровня: эти процессы останутся в состоянии ожидания. Понижение уровня блокировки с блокировки на запись до блокировки на чтение возможно всегда. В обоих случаях просто изменяется значение вида блокировки. По той причине, что функция lockf(3C) (в соответствии со стандартом /usr/group) не устанавливает блокировки на чтение, изменение уровня блокировки в случае использования этой функции невозможно. Ниже приведен пример блокировки сегмента с последующим изменением ее уровня:

       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) завершается неудчей. В последнем случае программу нужно было бы изменить для обработки подобной ситуации.

Теперь рассмотрим сходный пример с использованием функции lockf(3C). Так как она не позволяет выполнять блокировку на чтение, под блокировкой будет пониматься блокировка на запись.

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

       #include <unistd.h>
       
       long set3lock (this, here, next)
       long this, here, next;
       {
         /* Блокируем сегмент here */
         (void) lseek (fd, here, 0);
         if (lockf (fd, F_LOCK, sizeof (struct record)) < 0) {
           return (-1);
         }

         /* Блокируем сегмент this */
         (void) lseek (fd, this, 0);
         if (lockf (fd, F_LOCK, sizeof (struct record)) < 0) {
           /* Блокировка сегмента this не удалась.
              Разблокируем here */
           (void) lseek (fd, here, 0);
           (void) lockf (fd, F_ULOCK, sizeof (struct record));
           return (-1);
         }

         /* Блокируем сегмент next */
         (void) lseek (fd, next, 0);
         if (lockf (fd, F_LOCK, sizeof (struct record)) < 0) {
           /* Блокировка сегмента next не удалась.
              Разблокируем сегмент here...*/
           (void) lseek (fd, here, 0);
           (void) lockf (fd, F_ULOCK, sizeof (struct record));
           /*...и разблокируем сегмент this */
           (void) lseek (fd, this, 0);
           (void) lockf (fd, F_ULOCK, sizeof (struct record));
           return (-1);
           /* Не смогли заблокировать */
         }
         return (this);
       }

Блокировка снимается тем же способом, что и устанавливается, только в случае системного вызова fcntl(2) в качестве режима блокировки указывается F_UNLCK, а при использовании функции lockf(3C) - F_ULOCK. Разблокирование не может быть предотвращено другим процессом. Разблокирование можно производить только в отношении блокировок, ранее установленных тем же процессом. Разблокирование касается только сегментов, которые были заданы в предыдущем примере структурой lck. Можно производить разблокирование или изменять тип блокировки для части ранее блокированного сегмента, однако это может привести к появлению дополнительного элемента в системной таблице блокировок.

3.4. Получение информации о блокировке

Имеется возможность выявить процесс, мешающий установить блокировку. С помощью полученной информации можно узнать, какие бликоровки действуют для файла. Пусть блокировка устанавливается как в предыдущем примере, но при обращении к fcntl(2) используется операция F_GETLK. Если запрашиваемую блокировку установить нельзя, информация о первой мешающей этому блокировке будет возвращена процессу через структуру, адрес которой был передан системному вызову fcntl(2). В результате данные, переданные fcntl(2), будут заменены информацией о противодействующей блокировке. Эта информация включает два ранее не упоминавшихся элемента данных: l_pid и l_sysid. Они используются только операцией F_GETLK. (Для систем, не поддерживающих распределенную архитектуру, значение l_sysid игнорируется.) Два упомянутых поля полностью идентифицируют процесс, установивший блокировку.

Если блокировка, запрашиваемая системным вызовом fcntl(2) с использованием операции F_GETLK, может быть установлена, значением поля l_type становится F_UNLCK, а остальные поля в структуре не изменяются. Используем описанную возможность для вывода информации о всех сегментах файла, заблокированных другими процессами. Заметим, что если на один сегмент файла установлено несколько блокировок, то только первая из них будет найдена.

       struct flock lck;
       
       /* Получение и вывод информации о сегментах файла,
          блокированных на запись */
       (void) printf ("ид-р сис. ид-р проц. тип начало длина\n");
       lck.l_whence = 0;
       lck.l_start = 0L;
       lck.l_len = 0L;

       do {
         lck.l_type = F_WRLCK;
         (void) fcntl (fd, F_GETLK, &lck);
         if (lck.l_type != F_UNLCK) {
           (void) printf("%9d %9d %c %6d %5d\n",
             lck.l_sysid, lck.l_pid,
             (lck.l_type == F_WRLCK) ? 'W' : 'R',
             lck.l_start, lck.l_len);
           /* Если эта блокировка заведомо покрывает остаток файла,
              нет нужды выявлять другие блокировки */
           if (lck.l_len == 0) break;
           /* Иначе поищем новую блокировку после найденной */
           lck.l_start += lck.l_len;
         }
       } while (lck.l_type != F_UNLCK);

Системный вызов fcntl(2) с операцией F_GETLK всегда завершается успешно (то есть процесс не будет приостановлен и вызов не завершится аварийно), если, конечно, значения переданных параметров корректны.

Функция lockf(3C) с операцией F_TEST также может быть использована для выявления процесса, мешающего установить блокировку. Однако эта функция не способна определить заблокированный участок сегмента и то, какой процесс заблокировал его. Программа, использующая lockf(3C) для проверки факта блокировки файла, приведена ниже:

       /* Выявление заблокированного сегмента */
       
       /* Установка на начало файла */
       (void) lseek (fd, 0, 0L);

       /* Нулевой размер тестируемого сегмента
          означает проверку до конца файла */
       if (lockf (fd, F_TEST, 0L) < 0) {
         switch (errno) {
           case EACCES:
           case EAGAIN:
             (void) printf ("Файл блокирован другим процессом\n");
             break;
           case EBADF:
             /* Некорректные аргументы lockf */
             perror ("lockf");
             break;
           default:
             (void) printf (
               "lockf: непредусмотренная ошибка <%d>\n",errno);
             break;
         }
       }

Процесс, порожденный в результате выполнения системного вызова fork(2), наследует копии дескрипторов файлов, открытых процессом-предком. Кроме того, порождающий и порожденный процессы (для каждого файла) разделяют общий указатель текущей позиции в файле. Если процесс-предок изменит указатель файла, то изменение затронет и порожденный процесс. Такое положение влечет важные следствия при использовании блокировки сегментов. Если значение поля l_whence равно 1, то l_start указывает смещение начала блокируемого сегмента относительно указателя текущей позиции в файле. Если и порождающий, и порожденный процессы блокируют сегменты одного и того же файла, то существует вероятность, что при этом будет использоваться указатель текущей позиции, измененный другим процессом. Эта проблема существует и в случае использования функции lockf(3C) и является следствием требований стандарта /usr/group на блокировку сегментов. Если системный вызов fork(2) используется в программе наряду с блокировкой сегментов, то порожденный процесс при использовании любого метода блокировки должен закрыть и вновь открыть файл. В результате будет создан новый указатель текущей позиции в файле, которым можно будет манипулировать, не сталкиваясь с отмеченной проблемой. Другое решение состоит в том, чтобы использовать системный вызов fcntl(2) со значением поля l_whence 0 или 2, что делает блокировку независимой от указателя текущей позиции.

3.5. Управление тупиковыми ситуациями

Система блокировки сегментов позволяет в некоторой степени выявлять и обходить тупиковые ситуации. Эти средства обеспечивают тот же уровень защиты, что и соответствующая стандарту /usr/group функция lockf(3C). Средства обнаружения тупиковых ситуаций работают лишь для процессов, блокирующих сегменты и файлы на одном компьютере. Тупиковые ситуации потенциально могут встречаться только тогда, когда операционная система собирается приостановить процесс, обратившийся к системе блокировки. Система осуществляет поиск циклов в графе процессов, зависимых по блокировке. Если появится цикл, это приведет к бесконечному ожиданию возможности заблокировать сегмент. При выявлении подобной ситуации попытка блокировки заканчивается неудачей и значение errno будет равно соответствующему номеру ошибки, связанному с тупиковой ситуацией. Если нужно, чтобы процесс не использовал системный способ обнаружения тупиковых ситуаций, следует при блокировке вместо F_GETLKW использовать F_GETLK.

4. ВЫБОР СЛАБОЙ ИЛИ СИЛЬНОЙ БЛОКИРОВКИ

По причинам, описанным ниже (см. Сильная блокировка. Некоторые предупреждения), использование сильной блокировки не рекомендуется. Будет ли задействован контроль блокировки при любых системных вызовах, обслуживающих ввод-вывод, выясняется в момент этих вызовов в зависимости от режима доступа к файлу [см. chmod(2)]. Чтобы такой контроль осуществлялся, файл должен быть обычным, со взведенным битом переустановки идентификатора группы и без права на выполнение членами группы. Если эти условия не выполняются, все блокировки сегментов будут слабыми. Сильная блокировка может быть обеспечена следующим исходным текстом:

       #include <sys/types.h>
       #include <sys/stat.h>
       
       int mode;
       struct stat buf;
          . . .
       if (stat (filename, &buf) < 0) {
         perror ("программа");
         exit (2);
       }
       /* Получение текущего режима доступа */
       mode = buf.st_mode;
       /* Удаление разрешения на выполнение членами группы */
       mode &= (S_IEXEC >> 3);
       /* Взведение бита переустановки идентификатора группы */
       mode |= S_ISGID;
       if (chmod (filename, mode) < 0) {
         perror ("программа");
         exit (2);
       }
          . . .

С файлами, в которых должны блокироваться сегменты, не должно быть связано каких бы то ни было прав на выполнение. Это требование вызвано тем, что операционная система не поддерживает протокол блокировки сегментов при выполнении файла.

Помимо рассмотренного способа, сильная блокировка файла может быть легко установлена с использованием утилиты chmod(1):

       chmod  +l файл

Утилита ls(1) также была изменена с тем, чтобы при запросе с опцией -l отображать установленный режим блокировки. В результате выполнения запроса

       ls -l f1

будет выведена строка вида

       -rw---l--- 1 abc   other 1576 Dec  3 11:44 f1

4.1. Сильная блокировка. Некоторые предупреждения

4.2. Блокировка сегментов и развитие системы UNIX

В настоящее время проведена работа по реализации блокировки файлов и сегментов в распределенной среде UNIX. Компьютер, на котором выполняется процесс, запрашивающий блокировку, может не совпадать с компьютером, на котором находится блокируемый файл. В этом случае работающие на различных компьютерах процессы могут блокировать сегменты файлов, размещенных на одном из этих компьютеров или даже на другом компьютере. Блокировки на сегменты файла фиксируются на том компьютере, где расположен файл. Важно отметить, что механизм выявления/предотвращения тупиковых ситуаций определен только для блокировок, с которыми работают в пределах одного компьютера. Поэтому, чтобы механизм управления тупиковыми ситуациями работал, процесс должен в каждый данный момент времени работать с блокировками, зафиксированными ровно на одном компьютере. Если для процесса требуется вести блокировки на нескольких компьютерах сразу, рекомендуется не применять операций блокировки с ожиданием и выявлять тупиковые ситуации самостоятельно. Если процесс использует операции блокировки с ожиданием, то он должен обеспечить механизм выхода по времени таким образом, чтобы не "зависать" в ожидании получения возможности блокировки.


НазадОглавлениеВперед
КаталогИндекс раздела