sliver__

[File Locking] - Lock File technique 본문

CS/UNIX

[File Locking] - Lock File technique

sliver__ 2022. 10. 17. 13:21
728x90

[Lock file technique]

  1. lock file을 생성 또는 열려고 시도한다.
  2. 1)이 실패하면 1)을 반복한다.
  3. 1)이 성공하면 lock file 자원을 얻는다.

 

  • lock file이 atomic 해야한다.
fd = open("file.lck",O_WRONLY|O_CREAT|O_EXCL,mode);
  • O_CREAT는 파일이 없을 때 생성하라는 옵션이다.
  • O_EXCL은 파일이 이미 존재할 때 error return 하라는 옵션이다.
  • 그러므로 파일이 없을 때만 성공하는 로직이므로 atomic하다.

 

 

  • 아래는 lock file 예시 코드이다.
/* lockfile.c */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

/*
 * Lock by creating a lock file :
 */
static void
Lock(void) {
    int fd = -1;                /* Lock file descriptor */

    do  {
        fd = open("file.lck",O_WRONLY|O_CREAT|O_EXCL,0666);
        if ( fd == -1 ) {
            if ( errno == EEXIST ) {
                sleep(1);       /* Nap for a bit.. */
            }  else {
                fprintf(stderr,"%s: Creating lock file.lck\n",
                        strerror(errno));
                abort();        /* Failed */
            }
        }
    }  while ( fd == -1 );

    close(fd);                  /* No longer need file open */
}

/*
 * Unlock by releasing the lock file :
 */
static void
Unlock(void) {

    unlink("file.lck");         /* Release the lock file */
}

int
main(int argc,char **argv) {
    FILE *f = NULL;
    int i;
    int ch;
    int lck = 1;

    /*
     * If command line argument 1 is nolock or NOLOCK,
     * this program runs without using the Lock() and
     * Unlock() functions :
     */
    if ( argc >= 2 && !strcasecmp(argv[1],"NOLOCK") )
        lck = 0;                        /* No locking */

    printf("Process ID %ld started with %s\n",
            (long)getpid(),
            lck ? "locking" : "no locking");

    /*
     * Now create some rows of data in file.dat :
     */
    for ( i=0; i<1000; ++i ) {
        if ( lck )                      /* Using locks? */
            Lock();                     /* Yes, get lock */

        /*
         * Here we just update file.dat with new records. If
         * no locking is used while multiple processes do this,
         * some records will usually be lost. However, when
         * locking is used, no records are lost.
         *
         * Here we just open the file if it exists, otherwise
         * the file is opened for write.
         */
        f = fopen("file.dat","r+");     /* Open existing file */

        if ( !f && errno == ENOENT )
            f = fopen("file.dat","w");  /* Create file */

        if ( !f ) {
            fprintf(stderr,"%s: opening file.dat for r/w\n",
                    strerror(errno));
            if ( lck )
                Unlock();               /* Unlock */
            return 1;                   /* Failed */
        }

        /*
         * Seek to the end of the file, and add a record :
         */
        fseek(f,0,SEEK_END);            /* Seek to end of file */

        fprintf(f,"%05ld i=%06d ",(long)getpid(),i);
        for ( ch=''; ch<='z'; ++ch )
            fputc(ch,f);      /* A bunch of data to waste time */
        fputc('\n',f);

        fclose(f);

        if ( lck )                      /* Using locks? */
            Unlock();                   /* Yes, unlock */
    }

    /*
     * Announce our completion :
     */
    printf("Process ID %ld completed.\n",(long)getpid());
    return 0;
}

 

  • file lock을 한 경우와 하지 않은 경우 결과가 다르다.
    • file lock을 하지 않은 경우 쓰기가 겹쳐 loop * process 수 만큼 라인이 file.dat에 적히지 않는다.
  • Lock file 의 단점
    • multi-user system에서 한 명씩 요청을 수행할 수 밖에 없다.
    • NFS file system에서는 사용불가능하다.
    • 하나의 프로세스가 파일의 특정 부분을 사용하려면 파일 전체가 lock되어야 한다.

 

[더 세밀한 locking method]

  • read lock ( shared lock )은 파일의 같은 부분을 여러 프로세스가 읽을 수 있게 한다.
  • write lock ( exclusive lock )은 하나의 프로세스만 파일을 접근할 수 있게 한다.
  • 위 방법은 file locking에 비하여 더 효율적으로 프로세스가 파일을 다룰 수 있게 한다.
  • flock 함수는 아래와 같다.
#include <sys/file.h>

int flock(int fd, int operation);

#define LOCK_SH   0x01    /* shared file lock */
#define LOCK_EX   0x02    /* exclusive file lock */
#define LOCK_NB   0x04    /* don't block when locking */
#define LOCK_UN   0x08    /* unlock file */
  • LOCK_NB는 프로세스가 lock 요청을 걸었을 때 사용중이라면 -1을 return하고 errno에 EWOULDBLOCK을 적는다.
  • 해당 프로세스는 suspend되지않고 다른일을 할 수 있다.
  • flock의 장점
    • sleep이 수행되지 않으므로 성능증가
    • 정교한 lock 가능
    • NFS file system에서 사용가능
728x90
Comments