扩展阅读
  • linux c/c++ IP字符串转换成可比较大小的数字
  • 在win分区上安装linux和独立分区安装linux有什么区别?可以同时安装吗?(两个linux系统)
  • linux哪个版本好?linux操作系统版本详细介绍及选择方案推荐
  • 在虚拟机上安装的linux上,能像真的linux系统一样开发linux程序么?
  • secureCRT下Linux终端汉字乱码解决方法
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在有linux的盘)
  • Linux c字符串中不可打印字符转换成16进制
  • 红旗Linux主机可以通过127.0.0.1访问,但如何是连网的Win2000机器通过Linux的IP去访问Linux
  • Linux常用命令介绍:更改所属用户群组或档案属性
  • 安装vmware软件,不用再安装linux系统,就可以模拟linux系统了,然后可以在其上学习一下LINUX下的基本操作 了?
  • linux命令大全详细分类介绍及常用linux命令文档手册下载
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在没有linux的盘,只有DOS启动盘)
  • Linux Kernel 'sctp_v6_xmit()'函数信息泄露漏洞
  • 如何让win2000和linux共存。我装好WIN2000,再装LINUX7.0,但LILO只能找到LINUX,不能引导WIN2000
  • linux c下利用srand和rand函数生成随机字符串
  • 在windows中的VMware装了个linux,主板有两个串口,能做windows和linux的串口通信测试么,怎么测试这两个串口在linux是有效
  • Linux c++虚函数(virtual function)简单用法示例代码
  • 我们网站的服务器从windows2000迁往linux,ASP程序继续使用,可是我连LINUX的皮毛都不了解,大家告诉我LINUX下怎么建网站??
  • Docker官方镜像将会使用Alpine Linux替换Ubuntu
  • 中文Linux与西文Linus分别哪一个版是权威?I认为是:中科软的白旗Linux与西文的绿帽子Linux!大家的看法呢?
  • Linux下chmod命令详细介绍及用法举例
  • Windows2000和Linux双操作系统,Linux系统有问题,我直接把Linux分区删除后,Windows2000进不去了,怎么办???
  •  
    当前位置:  编程语言>c/c++

    Linux下glibc库文件锁:协同锁(advisory lock)和强制锁(mandatory lock)

     
        发布时间:2013-12-20  


        本文导语:  Linux系统上的文件锁主要分为协同锁(advisory lock)和强制锁(mandatory lock)。在Linux上使用的文件锁大部分为协同锁,而且使用强制锁的时候也要检查系统是否支持强制锁. 1)协同锁  协同锁要求参与操作的进程...

       Linux系统上的文件锁主要分为协同锁(advisory lock)和强制锁(mandatory lock)。在Linux上使用的文件锁大部分为协同锁,而且使用强制锁的时候也要检查系统是否支持强制锁.

        1)协同

      协同锁要求参与操作的进程之间协同合作。假设进程“A”获得一个WRITE锁,并开始向文件中写入内容;此时,进程“B”并没有试图获取一个锁,它仍然可以打开文件并向文件中写入内容。在此过程中,进程“B”就是一个非合作进程。如果进程“B”试图获取一个锁,那么整个过程就是一个合作的过程,从而可以保证操作的“序列化”。

      只有当参与操作的进程是协同合作的时候,协同锁才能发挥作用。协同锁有时也被称为“非强制”锁。有些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地测试此类文件是否存在。这种方法显然不太好,因为当产生文件的进程被杀后,锁文件依然存在,这样文件也许会被永久锁住。

        UUCP中把产生文件的进程号PID存入文件,但这样做仍然不保险,因为PID的利用是回收型的。这里是三个文件锁函数

        flock();

        lockf();

        fcntl();

        flock()是从BSD中衍生出来的,但目前在大多数UNIX系统上都能找到,在单个主机上flock()简单有效,但它不能在NFS工作Perl中也有一个有点让人迷惑的flock()函数,但却是在perl内部实现的。

        fcntl()是唯一的符合POSIX标准的文件锁实现,所以也是唯一可移植的。它也同时是最强大的文件锁--也是最难用的。在NFS文件系统上,fcntl()请求会被递交给叫rpc.lockd的守护进程,然后由它负责和主机端的lockd对话,和flock()

    不同,fcntl()可以实现记录层上的封锁。

       lockf()只是一个简化了的fcntl()文件锁接口

       无论你使用哪一种文件锁,请一定记住在锁生效之前用sync来更新你所有的文件输入/输出

      2)强制锁

      强制锁不需要参与操作的进程之间保持协同合作。它利用内核来查检每个打开、读取、写入操作,从而保证在调用这些操作时不违反文件上的锁规则。关于强制锁的更多信息,可以在kernal.org上找到。

      为了使能Linux中的强制锁功能,你需要在文件系统级别上打开它,同时在单个文件上打开它。其步骤是:

      (1)挂载文件系统时使用“-omand”参数

      (2)对于要打开强制锁功能的文件lock_file,必须打开set-group-ID位,关闭group-execute位。(选择此方法的原因是,当你关闭group-execute时,设置set-group-ID就没有实际的意义了)。

      检测系统是否支持强制锁的代码如下:  

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/wait.h>
    #include <stdarg.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <signal.h>
    #include <sys/wait.h>
            
    volatile sig_atomic_t sigflag;
    int pfd1[2], pfd2[2];
    sigset_t    newmask, oldmask, zeromask;
            
    void err_doit(int errnoflag, const char *fmt, va_list ap)
    {
        int    errno_save;
        char    buf[4096];
              
        errno_save = errno;
        vsprintf(buf, fmt, ap);
        if (errnoflag)
           sprintf(buf+strlen(buf), ": %s", strerror(errno_save));
        strcat(buf, "/n");
        fflush(stdout);
        fputs(buf, stderr);
        fflush(stderr);
        return;
    }
            
    void err_sys(const char *fmt, ...)
    {
        va_list        ap;
        va_start(ap, fmt);
        err_doit(1, fmt, ap);
        va_end(ap);
        exit(1);
    }
    void sig_usr(int signo)
    {
        sigflag = 1;
        return;
    }
    TELL_WAIT()
    {
        if (signal(SIGUSR1, sig_usr) == SIG_ERR)         /*SIGUSR1 为用户自定义信号*/
            err_sys("signal(SIGINT) error");
        if (signal(SIGUSR2, sig_usr) == SIG_ERR)
            err_sys("signal(SIGQUIT) error");
              
        sigemptyset(&zeromask);
              
        sigemptyset(&newmask);
        sigaddset(&newmask, SIGUSR1);
        sigaddset(&newmask, SIGUSR2);
            /*阻塞 SIGUSR1 和 SIGUSR2 并且保存当前信号掩码*/
        if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
            err_sys("SIG_BLOCK error");
    }  
            
    void WAIT_PARENT(void)
    {
        while( sigflag == 0)
            sigsuspend(&zeromask);    /*suspend()取消了所有信号屏蔽,等待父进程发来信号*/
        sigflag = 0;
            /*恢复信号掩码*/
        if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
            err_sys("SIG_SETMASK error");
    }
            
            
    int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
    {
        struct flock    lock;
        lock.l_type = type;
        lock.l_start = offset;
        lock.l_whence = whence;
        lock.l_len = len;
              
        return( fcntl(fd, cmd, &lock) );
    }
            
    void set_fl(int fd, int flags)
    {
        int     val;
        if ( (val = fcntl(fd, F_GETFL, 0)) < 0)
            err_sys("fcntl F_GETFL error");
            
        val |= flags;        /*置标志*/
            
        if (fcntl(fd, F_SETFL, val) < 0)
            err_sys("fcntl F_SETFL error");
    }
            
    void err_ret(const char *fmt, ...)
    {
        va_list        ap;
        va_start(ap, fmt);
        err_doit(1, fmt, ap);
        va_end(ap);
        return;
    }
            
            
    int main(void)
    {
        int        fd;
        pid_t        pid;
        char        buff[5];
        struct stat    statbuf;
              
        if ( (fd = open("templock", O_RDWR | O_CREAT | O_TRUNC, 0644)) < 0)
            err_sys("open error",buff);
              
        if (write(fd, "abcdef", 6) != 6)
            err_sys("write error");
            
        /*打开 set-group-ID(s-gid),并关闭组执行权限*/
        if (fstat(fd, &statbuf) < 0)
            err_sys("fstat error");
              
        if (fchmod(fd, (statbuf.st_mode & ~S_IXGRP) | S_ISGID) < 0)
            err_sys("fork error");
              
        TELL_WAIT();
        if ( (pid = fork()) < 0) {
            err_sys("fork error");
        } else if (pid > 0) {    /*父进程*/
                    /*整个文件写锁*/
        if (lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0)
            err_sys("write_lock error");
        kill(pid, SIGUSR1);    /*给子进程发送信号告知锁完成*/
              
        if (waitpid(pid, NULL, 0) < 0)
            err_sys("waitpid error");
        } else {
                WAIT_PARENT();    /*等待父进程设置锁*/
              
        set_fl(fd, O_NONBLOCK);  
              
        if (lock_reg(fd, F_SETLK, F_RDLCK, 0, SEEK_SET, 0) != -1)
            err_sys("child: read_lock succeeded");
        printf("read_lock of already-locked region return %d/n", errno);
            
        if (lseek(fd, 0, SEEK_SET) == -1)
            err_sys("lseek, error");
            
        if (read(fd, buff, 2) < 0)
        err_ret("read failed (mandatory locking wroks)");
        else
            printf("read OK (no mandatory locking), buff = %2.2s/n", buff);
        }
        exit(0);
    }



    相关文章推荐:


    站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3