当多个进程同时访问操作同一个文件时,我们怎么保证文件数据的正确性。

linux通常采用的方法是文件上锁,来避免共享资源的产生竞争状态。

文件锁包括建议性锁和强制性的锁:

建议性的锁 :顾名思义,相对温柔一些,在对文件进行锁操作时,会检测是否已经有锁存在,并且尊重已有的锁。在一般的情况下,内核和系统都不使用建议锁。

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

在linux中对文件进行锁操作,可以使用lockf()和fcntl()这两个函数:

前者对文件施加建议性锁,后者为两种锁都行。另外fcntl还可以对文件的某一记录上锁。
fcntl函数原型:

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

fd为文件描述符

cmd为一些命令参数

flcok结构体用来设置记录锁的具体状态。

fcntl() 对已打开的文件描述符进行操作,并根据命令参数的不同能够执行不同的任务。

关于文件锁的几个命令选项如下:

F_GETLK 根据lock参数值,决定是否上文件锁

F_SETLK 设置lock参数值的文件锁

F_SETLKW 这是 F_GETLK的阻塞版本,在无法获取锁时,会进入睡眠状态

    flock结构体的定义如下:
       struct flock {
                 short l_type;
                 off_t l_start;
                 short l_whence;
                 off_t l_len;
                 pid_t l_pid;
       }

l_type有三个选项:    

F_RDLCK  : 共享锁,只读用

F_WRLCK : 独占锁(写操作锁)       

F_UNLCK  : 解除锁定

l_start 为相对位移量
                  l_whence 必须是以下几个值之一( 在 unistd.h 中定义):
                  SEEK_SET : 文件开始位置
                  SEEK_CUR: 文件当前位置
                  SEEK_END: 文件末尾位置
                   l_len 加锁的长度
                   l_pid当前文件操作的进程id号
文件2 test01.c,代码如下:

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)

{

    FILE  *fp = NULL;
    int   i   = ;    //20秒时间
    
    //打开文件
    if ((fp = fopen("./test.ok", "r+b")) == NULL) 
        printf("file open error!\n");     //给该文件加锁
    if (flock(fp->_fileno, LOCK_EX) != ) 
        printf("file lock by others\n");     //进入循环,加锁时间为20秒,打印倒计时
    while() 
    {   
        printf("%d\n", i--);
        sleep();
        if (i == )
            break;
    }     //20秒后退出,关闭文件
    fclose(fp);     //文件解锁
    flock(fp->_fileno, LOCK_UN);
    return ;
}

文件2 test02.c,代码如下:

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h> int main(void)
{
    FILE *fp = NULL;
    int  i   = ;
    
    //打开文件
    if ((fp = fopen("./test.ok", "r+b")) == NULL) 
        printf("file open error!\n");     flock(fp->_fileno, LOCK_EX); //文件加锁     while() //进入循环
    {   
        printf("%d\n", i++);
        sleep();
    }     fclose(fp); //关闭文件     flock(fp->_fileno, LOCK_UN); //释放文件锁     return ;

 首先运行test01.c,紧接着运行test02.c(运行test01.c后20秒内要运行test02.c否则看不到现象)

 现象:

test01.c执行起来以后,开始倒计时。

此时运行test02.c会阻塞在加锁处。

当test01.c运行20秒后关闭文件,并释放文件锁后,test02.c会开始运行。

测试:

1.************************************

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    FILE  *fp = NULL;
    int   i   = 20;    //20秒时间
    //打开文件
    if ((fp = fopen("./test.ok", "r+")) == NULL)
        printf("file open error!\n");
    //给该文件加锁
    if (flock(fp, LOCK_NB|LOCK_EX) != 0)
    {
        printf("file lock fail \n");
            //进入循环,加锁时间为20秒,打印倒计时
    }
    else
    {
            while(1)
            {
                printf("倒计时%d秒\n", i--);
                sleep(1);
                if (i == 0)
                {
                   printf("倒计时结束,程序退出  !\n", i--);
                   break;
                }
            }
    }
    //20秒后退出,关闭文件
    fclose(fp);
    //文件解锁
    flock(fp, LOCK_UN);
    //20秒后退出,关闭文件
    //fclose(fp);
    return 0;
}

2.************************************************

#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
    FILE *fp = NULL;
    int  i   = 0;
    //打开文件
    if ((fp = fopen("./test.ok", "r+b")) == NULL)
        printf("file open error!\n");
    flock(fp, LOCK_UN); //释放文件锁
    if(flock(fp, LOCK_EX) != 0) //文件加锁
    {
        printf("gei wenjian lock~~ \n");
    }
    else
    {
            while(1) //进入循环
            {
                printf("前进到第%d秒\n", i++);
                sleep(1);
                if(i == 20)
                    break;
            }
    }
    fclose(fp); //关闭文件
    flock(fp, LOCK_UN); //释放文件锁
    return 0;
}

测试竟然不成功。

Linux 文件锁的更多相关文章

  1. Linux文件锁flock

    Linux文件锁flock 在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock. flock,建议性锁 ...

  2. linux文件锁flock【转】

    转自: https://www.cnblogs.com/kex1n/p/7100107.html linux文件锁flock   在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要 ...

  3. 每天进步一点点——Linux文件锁编程flock

    转载请注明出处:http://blog.csdn.net/cywosp/article/details/30083015 1. 场景概述     在多线程开发中.相互排斥锁能够用于对临界资源的保护,防 ...

  4. Linux文件锁学习-flock, lockf, fcntl

    参考  linux中fcntl().lockf.flock的区别 这三个函数的作用都是给文件加锁,那它们有什么区别呢? 首先flock和fcntl是系统调用,而lockf是库函数.lockf实际上是f ...

  5. linux文件锁的应用,POSIX,unix标准,linux标准

    1. perl,flock加锁.java也能加锁. 2. 先创建文件并打开,才能加锁(写打开?). 3. 可以用于判断进程是否一直在运行(用另一进程判断),如果锁一直在,则进程在:锁不在,则原进程或意 ...

  6. Linux文件锁【转】

    本文转载自:http://blog.csdn.net/dragon_li_chen/article/details/17147911 一.文件锁的分类: 翻阅参考资料,你会发现文件锁可以进行很多的分类 ...

  7. linux 文件锁flock,lockf,fcntl

    1.flock,lockf,fcntl之间区别 先上结论:flock是文件锁,锁的粒度是整个文件,就是说如果一个进程对一个文件加了LOCK_EX类型的锁,别的进程是不能对这个文件加锁的. lockf是 ...

  8. linux文件锁

    http://blog.chinaunix.net/uid-25324849-id-3077304.html 在SHELL中实现文件锁,有两种简单的方式.(1)一是利用普通文件,在脚本启动时检查特定文 ...

  9. Linux文件锁flock ,检测进程是否已经存在

    在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock.  头文件:#include<sys/fil ...

随机推荐

  1. 全面理解面向对象的 JavaScript (share)

     以下分享自:  http://www.ibm.com/developerworks/cn/web/1304_zengyz_jsoo/   简介: JavaScript 函数式脚本语言特性以及其看似随 ...

  2. JQUERY添加、删除元素、eq()方法;

    一.jQuery - 添加元素 1.append() - 在被选元素内部的结尾插入指定内容 2.prepend() - 在被选元素内部的开头插入指定内容 3.after() - 在被选元素之后插入内容 ...

  3. poj3160 强连通+记忆化搜索

    题意:有一张 n 点 m 边的有向无环图,每个点有各自的权值,可正可负,现在从一个点开始走,一直走到不能走到其他点为止,每经过一个点,可以选择获得或不获得它的权值,每个点可以走多次,但是权值只能获得一 ...

  4. Sporadic IOException: Failed to persist config

    问题 在调用Jenkins API来更新Job的时候报错‘Sporadic IOException: Failed to persist config’. 原因 https://issues.jenk ...

  5. QTreeWidget创建

    QTreeWidget.顾名思义,这个类用来展示树型结构.同前面说的QListWidget类似,这个类需要同另外一个辅助类QTreeWidgetItem一同使用.不过,既然是提供方面的封装类,即便是看 ...

  6. foreach属性-动态-mybatis中使用map类型参数,其中key为列名,value为列值

    http://zhangxiong0301.iteye.com/blog/2242723 最近有个需求,就是使用mybatis时,向mysql中插入数据,其参数为map类型,map里面的key为列名, ...

  7. lua遍历文件夹, zerobrane下载

    参考的这个http://www.cnblogs.com/jiufangding/p/3931585.html,配合批处理. zerobrane下载(上一篇博客忘掉了): http://files.cn ...

  8. 037. asp.netWeb用户控件之五使用用户控件实现文件上传功能

    fileUpload.ascx代码: <%@ Control Language="C#" AutoEventWireup="true" CodeFile= ...

  9. Python chr() ord() unichr()

    chr()函数用一个范围在range(256)内的(就是0-255)整数作参数,返回一个对应的字符. unichr()跟它一样,只不过返回的是Unicode字符,这个从Python 2.0才加入的un ...

  10. 为什么引用不了App_Code里的类(报“未能找到类型或命名空间名称”错误)

    在Web应用程序中不能通过右键项目-〉”添加“-〉”添加ASP.NET文件夹“方式添加 .因为Web应用程序中App_Code就不存在 . 不过可以通过手动的方式创建,添加一个文件夹命名为App_Co ...