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

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

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

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

Пример, иллюстрирующий режимы блокировки:

#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("Ошибка при :

      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;

}

Этот пример иллюстрирует возможности сериализации процессов. Тем не менее здесь все равно возможны чтение и запись в процессе-потомке. Такой вариант блокировки называется 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
2004-06-22