next up previous contents
Next: Блокировка частей файла и Up: Блокировка файлов. Previous: Структура flock   Contents

Режимы блокировки.

Функции блокирования можно осуществлять в следующих режимах.

Замечание: Если нужно предусмотреть для файла блокировку по записи (F_WRLCK), файл должен быть открыт для записи (O_WRONLY). И наоборот, если необходима блокировка по чтению (F_RDLCK), файл открывается в режиме чтения (O_RDONLY). Это означает также, что блокировки не должны одновременно устанавливаться на определенный байт. Пример для иллюстрации режимов блокировки (рис. 15):

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <fcntl.h>

#include <errno.h>

#include <sys/types.h>

#include <sys/stat.h>

#define FNAME "locki.lck"

 

void status(struct flock *lock)

{

  printf("Status: ");

  switch(lock->l_type)

  {

    case F_UNLCK: printf("F_UNLCK (Блокировка снята)\n");

                  break;

    case F_RDLCK: printf("F_RDLCK (pid: %d) (Блокировка по чтению)\n",

                  lock->l_pid);

                  break;

    case F_WRLCK: printf("F_WRLCK (pid: %d) (Блокировка по записи)\n",

                  lock->l_pid);

                  break;

    default : break;

  }

}

 

int main(int argc, char **argv)

{

  struct flock lock;

  int fd;

  char buffer[100];

  fd = open(FNAME, O_WRONLY|O_CREAT|O_APPEND, S_IRWXU);

  memset(&lock, 0, sizeof(struct flock));

  /*Проверим, установлена ли блокировка*/

  fcntl(fd, F_GETLK, &lock);

  if(lock.l_type==F_WRLCK || lock.l_type==F_RDLCK)

  {

    status(&lock);

    memset(&lock,0,sizeof(struct flock));

    lock.l_type = F_UNLCK;

    if (fcntl(fd, F_SETLK, &lock) < 0)

      printf("Fehler : fcntl(fd, F_SETLK, F_UNLCK) (%s)\n",

        strerror(errno));

    else

      printf("Успешно снята блокировка:

        fcntl(fd, F_SETLK, F_UNLCK)\n");

  }

  status(&lock);

  write(STDOUT_FILENO,"\nВВедены данные: ",

      sizeof("\nВведены данные: "));

  while((read(1,puffer,100))>1)

     write(fd,buffer,100);

  memset(&lock, 0, sizeof(struct flock));

  lock.l_type = F_WRLCK;

  lock.l_start=0;

  lock.l_whence = SEEK_SET;

  lock.l_len=0;

  lock.l_pid = getpid();

  if (fcntl(fd, F_SETLK, &lock) < 0)

    printf("Ошибка при: fcntl(fd, F_SETLK, F_WRLCK)(%s)\n",

      strerror(errno));

  else

    printf("Успешно: fcntl(fd, F_SETLK, F_WRLCK)\n");

  status(&lock);

  switch(fork())

  {

    case -1 : exit(0);

    case 0 : if(lock.l_type == F_WRLCK)

               {

                  printf("Потомок:Невозможна запись

                         в файл (F_WRLCK)\n");

                  exit(0);

               }

             else

               printf("Потомок готов к записи в файл\n") ;

             exit(0);

    default : wait(NULL); break;

  }

  close(fd);

  return 0;

}

Рис. 15. Упорядоченная запись с блокировкой.

Этот пример показывает возможности сериализации процессов. Тем не менее, здесь все равно существует возможность чтения и записи в процессе-потомке. Такой вариант блокировки называется advisory locking (необязательная блокировка). При его установке не производится никакая дополнительная проверка, должны ли системные функции open, read и write при вызове запрещаться из-за блокировки. Для advisory locking принимается, что пользователь сам является ответственным за проверку того, существуют ли определенные блокировки или нет. Невозможно запретить ВСЕМ процессам доступ к файлу. Только процессы, опрашивающие наличие блокировки с помощью fcntl, блокируются при ее наличии (не всегда).

Для других случаев имеются так называемые строгие блокировки (mandatory locking). Строгие блокировки запрещают процессу получать доступ функциями read или write к данным, которые были блокированы другим процессом ранее через fcntl.

Строгие блокировки можно разрешить, установив бит Set-Group-ID и сняв бит выполнения для группы, например:

int mandatory_lock(int fd)

{

  struct stat statbuffer;

  if(fstat(fd, &statbuffer) < 0)

  {

    fprintf(stderr, "Ошибка при вызове fstat.......\n");

    return 0;

  }

  if(fchmod(fd (statbuffer.st_mode & ~S_IXGRP) | S_ISGID) < 0)

  {

    fprintf(stderr, "Невозможно установить строгую блокировку...\n");

    return 0;

  }

  return 1;

}

Строгая блокировка является зависимой от системы. Однако, она не может предотвратить удаление файла через unlink().

Если с помощью open() открывается файл с флагами O_TRUNC и O_CREAT и для этого файла установлена строгая блокировка, то возвращается ошибка со значением errno=EAGAIN.


next up previous contents
Next: Блокировка частей файла и Up: Блокировка файлов. Previous: Структура flock   Contents
2003-12-09