Chinaunix首页 | 论坛 | 博客
  • 博客访问: 334101
  • 博文数量: 214
  • 博客积分: 4258
  • 博客等级: 上校
  • 技术积分: 2021
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-02 09:16
个人简介

http://blog.csdn.net/ly21st http://ly21st.blog.chinaunix.net

文章分类

全部博文(214)

文章存档

2018年(16)

2015年(1)

2014年(2)

2012年(22)

2011年(173)

分类: LINUX

2011-09-16 14:35:53

有两种基本的文件上锁形式,它们是

1)文件上锁;

2)上锁的区域。

  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7

  8 void lock_file(void)

  9 {

 10    int fd = -1;

 11    do{

 12       fd = open("file.lck",O_WRONLY|O_CREAT|O_EXCL,0666);

 13       if ( fd==-1 ) {

 14             if ( errno == EEXIST )

 15                sleep(1);

 16             else {

 17                fprintf(stderr,"%s:create lock file file.lck\n",strerror(errno));

 18                abort();

 19             }

 20        }

 21    }while(fd==-1);

 22    close(fd);

 23 }

 24

  25 void unlock_file(void)

 26 {

 27    unlink("file.lck");

 28 }

 29

 30 int main(int argc, char **argv)

 31 {

 32    FILE *fp;

 33    char ch;

 34    int lock=1;

 35    int i;

 36

 37    if (argc >=2 && strcasecmp(argv[1],"nolock") )

 38       lock = 0;

 39    for (i=0; i<1000; i++)

 40    {

 41       if (lock)

 42          lock_file();

 43       fp=fopen("file.dat","r+");

 44       if (fp ==NULL && errno ==ENOENT )

 45          fp=fopen("file.dat","w");

 46       if (!fp){

 47          printf("open file.dat error\n");

 48          if (lock)

 49             unlock_file();

 50          return 1;

 51       }

 52       fseek(fp,0,SEEK_END);

 53       fprintf(fp,"%05ld   i=%d   ",(long)getpid(),i);

 54       for(ch=' '; ch < 'z'; ch++)

 55       {

 56          fputc(ch,fp);

 57          sleep(0.000005);

 58       }

 59       fputc('\n',fp);

 60       fclose(fp);

 61

 62       if (lock)

 63          unlock_file();

 64    }

 65    printf("process %ld completed\n",(long)getpid());

 66    return 0;

 67 }

但是,上面上锁文件的一些缺点是:

1)当使用sleep()时,两次失败的试图之间有很长的反应时间;

2)NFS文件系统上使用时,它不可靠;

3)它是粗粒度上锁(这意味着进程上锁整个文件);

因此要考虑其他文件上锁的方法。

 

使用flock()上锁

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

flock()函数具有一些优点超过上锁文件技术:

1)不包含附加的上锁条件;

2)重新上锁时,不调用sleep(),提供了改进的性能;

3)更细粒度的上锁允许上锁共享或独占;

4)容许上锁控制在NFS安装文件系统上

 

 

记录上锁:

int   lockf(int  fd,  int  request,  off_t  size);

该函数是要被Posix fcntl()接口放弃的,不再对它进行详细说明。

 

使用fcntl()上锁

#include

#include

 

int fcntl(int fd, int cmd);

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd, struct flock *lock);

      F_GETFL

              Read the file status flags.

 

       F_SETFL

              Set  the  file status flags to the value specified by arg.  File access mode (O_RDONLY,

              O_WRONLY, O_RDWR) and file creation flags (i.e., O_CREAT, O_EXCL, O_NOCTTY, O_TRUNC) in

              arg  are  ignored.   On  Linux  this  command  can  only  change the O_APPEND, O_ASYNC,

              O_DIRECT, O_NOATIME, and O_NONBLOCK flags.

 

   Advisory locking

       F_GETLK, F_SETLK and F_SETLKW are used to acquire, release, and  test  for  the  existence  of

       record  locks (also known as file-segment or file-region locks).  The third argument lock is a

       pointer to a structure that has at least the following fields (in unspecified order).

 

         struct flock {

             ...

             short l_type;    /* Type of lock: F_RDLCK,

                                 F_WRLCK, F_UNLCK */

             short l_whence;  /* How to interpret l_start:

                                 SEEK_SET, SEEK_CUR, SEEK_END */

             off_t l_start;   /* Starting offset for lock */

             off_t l_len;     /* Number of bytes to lock */

             pid_t l_pid;     /* PID of process blocking our lock

                        (F_GETLK only) */

             ...

         };

 

Mandatory locking

       (Non-POSIX.)   The above record locks may be either advisory or mandatory, and are advisory by

       default.

 

       Advisory locks are not enforced and are useful only between cooperating processes.

 

       Mandatory locks are enforced for all processes.  If a process tries to perform an incompatible

       access  (e.g.,  read(2) or write(2)) on a file region that has an incompatible mandatory lock,

       then the result depends upon whether the O_NONBLOCK flag is enabled for its open file descrip-

       tion.   If  the  O_NONBLOCK flag is not enabled, then system call is blocked until the lock is

       removed or converted to a mode that is compatible with the access.  If the O_NONBLOCK flag  is enabled, then the system call fails with the error EAGAIN or EWOULDBLOCK.

 

       To make use of mandatory locks, mandatory locking must be enabled both on the file system that

       contains the file to be locked, and on the file itself.  Mandatory locking  is  enabled  on  a file  system  using  the  "-o  mand" option to mount(8), or the MS_MANDLOCK flag for mount(2).Mandatory locking is enabled on a file by disabling group execute permission on the  file  and enabling the set-group-ID permission bit (see chmod(1) and chmod(2)).

阅读(301) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~