文件锁

来源:互联网 发布:centos开mc服务器 编辑:程序博客网 时间:2024/05/18 17:59

在文件已经共享的情况下,当多个用户共同使用时,如何对文件进行访问呢?linux采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。锁分为建议锁和强制锁

建议锁:要求每个上锁文件的进程都要检查是否有锁存在,并尊重已有的锁,一般情况下内核和系统都不使用建议性锁。

强制锁:由内核执行的锁,当一个文件被上锁进行写入的时候,内核将阻止其他任何文件对其进行读写操作,采用强制性锁对性能影响很大,每次读写都必须检查是否有锁存在。

上锁主要有两个函数:lockf()--------对文件施加建议性锁

                                     fcntl()--------可以施加建议性锁和强制性锁,并且可以施加建议性锁

记录锁分为读取锁和写入锁,读取锁是共享的,但写入锁是互斥的,也就是同一时刻只能有一个进程在文件的某个部分添加写入锁,当然文件不能同时加入写入锁和读取锁

ps:fcntl()不仅可以管理文件锁,而且可以获得和设置文件描述符和文件描述符标志,文件描述符的复制等功能,下面就是如何添加记录锁

fcntl()函数语法:




lock结构体的定义:

struct flock{    shrot l_type ;    off_t l_shart ;    short l_whence ;    off_t l_len ;    pid_t l_pid ;}

lock结构中每个变量含义如下


ps:为了加锁整个文件通常的做法是将l_start设置为0,l_whenec设置为seek_set,l_len设置为0

这里有个使用文件记录锁得例子

文件记录锁的代码:

int lock_set(int fd, int type){    struct flock old_lock, lock;    lock.l_whence = SEEK_SET ;    lock.l_start = 0;    lock.l_len = 0 ;    lock.l_type = type ;    lock.l_pid = -1 ;    /*F_GETLK判断文件是否能根据lock中的描述上锁,如果可以上锁则将flock结构中的l_type设置成F_UNLCK,如果    不能上锁l_pid设置成拥有文件锁得进程号,其他的不变*/    fcntl(fd, F_GETLK, &lock) ;    if (lock.l_type != F_UNLCK)//判断文件不能上锁的原因    {        if (lock.l_type == F_RDLCK)//文件有读锁了        {            printf("read lock aleady set by %d\n", lock.l_pid) ;        }        else if (lock.l_pid = F_WRLCK)//文件有写锁了        {            printf("Wirte lock aleady set by %d\n", lock.l_pid) ;        }    }    lock.l_type = type ;//此时肯能已经被F_GETLK修改过    /*进行阻塞式上锁,F_SETLKW是F_SETLK的阻塞版本,如果没有获取到锁    就会进入睡眠状态,如果可以获取到锁或者捕捉到信号就会返回*/    if ((fcntl(fd, F_SETLKW, &lock)))    {        printf("lock failed:type = %d\n", lock.l_type) ;        return 1 ;    }    switch(lock.l_type)    {        case F_RDLCK:        {            printf("read lock set by %d\n", getpid()) ;        }        break ;        case F_WRLCK:        {            printf("write lock set by %d\n", getpid()) ;        }        break ;        case F_UNLCK:        {            printf("release lock set by %d\n", getpid()) ;        }        break ;        default:        break ;    }    return 0 ;}

下面是测试实例,先加入写入锁,最后再释放锁得过程。可以打开两个终端进行测试

#include <unistd.h>#include <sys/file.h>#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include "lock_set.c"int main(){    int fd ;    fd = open("hello", O_RDWR| O_CREAT, 0644) ;    if (fd < 0)    {        printf("open file error\n") ;        exit(1) ;    }    lock_set(fd, F_WRLCK) ;//给文件加上写入锁    getchar() ;//从终端获取一个输入字符    lock_set(fd, F_UNLCK) ;//给文件解锁    getchar() ;    close(fd) ;    exit(0) ;}

终端1:

   

终端2:


等终端1解锁之后

终端1:


终端2:


可以看出写锁不是共享的,只能有一个 进程添加写锁

同样的原理试验读锁,发现读锁是可以共享的

在一个终端加入读锁,在另一个终端加入写锁也是不行的。


原创粉丝点击