表头文件  #include<sys/file.h>

  定义函数  int flock(int fd,int operation);

  函数说明  flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。此函数只能锁定整个文件,无法锁定文件的某一区域。

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

 
flock,建议性锁,不具备强制性。一个进程使用flock将文件锁住,另一个进程可以直接操作正在被锁的文件,修改文件中的数据,原因在于flock只是用于检测文件是否被加锁,针对文件已经被加锁,另一个进程写入数据的情况,内核不会阻止这个进程的写入操作,也就是建议性锁的内核处理策略。
 

 参数  operation有下列四种情况:

  LOCK_SH 建立共享锁定。多个进程可同时对同一个文件作共享锁定。

  LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。

  LOCK_UN 解除文件锁定状态。

  LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。

  单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()或fork()时文件描述词不会继承此种锁定。

  返回值  返回0表示成功,若有错误则返回-1,错误代码存于errno。

 
进程使用flock尝试锁文件时,如果文件已经被其他进程锁住,进程会被阻塞直到锁被释放掉,或者在调用flock的时候,采用LOCK_NB参数,在尝试锁住该文件的时候,发现已经被其他服务锁住,会返回错误,errno错误码为EWOULDBLOCK。即提供两种工作模式:阻塞与非阻塞类型。
 
服务会阻塞等待直到锁被释放:
flock(lockfd,LOCK_EX)
服务会返回错误发现文件已经被锁住时:
ret  = flock(lockfd,LOCK_EX|LOCK_NB)
同时ret = -1, errno = EWOULDBLOCK 
 
flock锁的释放非常具有特色,即可调用LOCK_UN参数来释放文件锁,也可以通过关闭fd的方式来释放文件锁(flock的第一个参数是fd),意味着flock会随着进程的关闭而被自动释放掉。
 
flock其中的一个使用场景为:检测进程是否已经存在;
int checkexit(char* pfile){
if (pfile == NULL)
return -;
int lockfd = open(pfile,O_RDWR);
if (lockfd == -)
return -;
int iret = flock(lockfd,LOCK_EX|LOCK_NB)
if (iret == -)
return -; return ;
}

下面为两个进程的实例:

file1.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h> int main(void)
{
int fp = open("file_lock.test", O_WRONLY);
int i = ; if (fp == -) //打开文件
{
printf("file1 open error!\n");
}
else{
printf("file1 open success!\n");
} if (flock(fp, LOCK_EX) != ) //给该文件加锁
{
printf("file1 lock by others\n");
}
else{
printf("file1 no user by others\n");
}
while () //进入循环,加锁时间为20秒,打印倒计时
{
printf("%d\n", i--);
sleep();
if (i == )
break;
}
close(fp); //20秒后退出,关闭文件
flock(fp, LOCK_UN); //文件解锁
return ; }

file2.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h> int main(void)
{
int fp = open("file_lock.test", O_WRONLY);
int i = ; if (fp == -) //打开文件
{
printf("file2 open error!\n");
}else{
printf("file2 open success!\n");
} if (flock(fp, LOCK_EX) != ) //给该文件加锁
{
printf("file2 lock by others\n");
}
else{
printf("file2 no user by others\n");
}
while() //进入循环
{
printf("%d\n", i++);
sleep();
}
close(fp); //关闭文件
flock(fp, LOCK_UN); //释放文件锁
return ; }
首先运行file1.c,紧接着运行file2.c(运行file1.c后20秒内要运行file2.c否则看不到现象)
现象是:file1.c执行起来以后,开始倒计时。此时运行file2.c会阻塞在加锁处。当file1.c运行20秒后关闭文件,并释放文件锁后,file2.c会开始运行。

1、4个文件,a进程文件a1,a2,b进程b1,b2
2、a进程加锁文件a1,b进程加锁文件b1
3、a进程创建a2文件,然后轮询查看b2文件是否存在(这里可以轮询,因为时间很短),不存在代表b进程还没创建,b进程同理
4、a进程轮询到b2文件存在了,代表b进程已经创建并可能在对b1文件加锁,此时删除文件b2,代表a进程已经加锁完毕,允许b进程读取a进程的锁,b进程同理
5、a进程监听文件a2,如果a2被删除,代表b进程进行到了步骤4已经对b1加锁完成,可以开始读取b1文件的锁(不能直接监听a2文件删除,也就是不能跳过34步,这也是最难想的一部分,如果那样可能此时b进程还没创建,和b进程创建完成并加锁完成的状态是一样的,就会让进程a误以为进程b加锁完成),b进程同理

a.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h> #define a1 "a1"
#define a2 "a2"
#define b1 "b1"
#define b2 "b2" void observer_file_exist(char* file_path){
int lockFD = access(file_path, F_OK);
while (lockFD == -){
lockFD = access(file_path, F_OK);
printf("wait %s create!\n", file_path);
sleep();
}
printf("%s create finish!\n", file_path);
} void observer_file_delete(char* file_path){
int lockFD = access(file_path, F_OK);
while (lockFD != -){
lockFD = access(file_path, F_OK);
printf("wait %s to be delete!\n", file_path);
sleep();
}
printf("%s create finish!\n", file_path);
} void remove_path_file(char* file_path){
int lockFD = access(file_path,F_OK);
if(lockFD!=-){
printf("%s exsit remove ... ing!\n",file_path);
int result=remove(file_path);
printf("%s exsit remove finish!\n",file_path);
}else{
printf("%s not exsit!\n",file_path);
}
} int main(void)
{ int fd1 = open(a1, O_WRONLY | O_CREAT,);;
if (fd1 == -) //打开文件
{
printf("%s has been created and completed !\n", a1);
}
else{
printf("%s crate success!\n", a1);
} if (flock(fd1, LOCK_EX) != ) //给该文件加锁
{
printf("no user by others, %s lock success\n",a1);
}else{
printf("lock by others ,%s lock fail \n",a1);
} int fd2 = open(a2, O_WRONLY | O_CREAT,);;
if (fd2 == -) //打开文件
{
printf("%s has been created and completed !\n", a2);
}
else{
printf("%s crate success!\n", a2);
}
close(fd2);
observer_file_exist(b2);
remove_path_file(b2);
observer_file_delete(a2);
printf("b process crate success!\n"); printf("wait %s release lock.\n",b1);
int fdb1 = open(b1, O_WRONLY);
if (flock(fdb1, LOCK_EX) == ){
printf("%s the file was unlocked \n",b1);
}else{
printf("%s the file was not unlocked. \n",b1);
} //close(fd1);
return ; }

b.c

#include <stdio.h>
#include <stdlib.h>
#include <sys/file.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h> #define a1 "a1"
#define a2 "a2"
#define b1 "b1"
#define b2 "b2" void observer_file_exist(char* file_path){
int lockFD = access(file_path,F_OK);
while(lockFD == -){
lockFD = access(file_path,F_OK);
printf("wait %s create!\n",file_path);
sleep();
}
printf("%s create finish!\n",file_path);
} void observer_file_delete(char* file_path){
int lockFD = access(file_path,F_OK);
while(lockFD != -){
lockFD = access(file_path,F_OK);
printf("wait %s to be delete!\n",file_path);
sleep();
}
printf("%s create finish!\n",file_path);
} void remove_path_file(char* file_path){
int lockFD = access(file_path,F_OK);
if(lockFD!=-){
printf("%s exsit remove ... ing!\n",file_path);
int result=remove(file_path);
printf("%s exsit remove finish!\n",file_path);
}else{
printf("%s not exsit!\n",file_path);
}
} int main(void)
{ int fd1 = open(b1, O_WRONLY|O_CREAT,);;
if (fd1 == -) //打开文件
{
printf("%s has been created and completed !\n",b1);
}else{
printf("%s crate success!\n",b1);
} if (flock(fd1, LOCK_EX) == ) //给该文件加锁
{
printf("no user by others, %s lock success\n",b1);
}else{
printf("lock by others ,%s lock fail \n",b1);
} int fd2 = open(b2, O_WRONLY|O_CREAT,);;
if (fd2 == -) //打开文件
{
printf("%s has been created and completed !\n",b2);
}else{
printf("%s crate success!\n",b2);
}
close(fd2);
observer_file_exist(a2);
remove_path_file(a2);
observer_file_delete(b2);
printf("a process crate success!\n"); printf("wait %s release lock.\n",a1);
int fda1 = open(a1, O_WRONLY);
if(flock(fda1, LOCK_EX)==){
printf("%s the file was unlocked.\n",a1);
}
else{
printf("%s the file was not unlocked.\n",a1);
} //close(fd1);
return ; }

Linux 文件锁flock 实现两个进程相互监听存活状态的更多相关文章

  1. 本地启动服务,两个进程分别监听两个端口,导致两个 URL 不同

    问题描述: 本地启了两个服务:A(http://localhost:8001) B(http://localhost:8000),A 项目要怎么才能关联到 B 项目,也就是 A 项目请求怎么跳到 B ...

  2. linux文件锁flock【转】

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

  3. Linux文件锁flock

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

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

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

  5. linux网络连接的查看和端口的监听

    网络软件都是由客户端和服务端组成,由服务端在服务器上监听指定的端口处理接收到的数据,而客户端是向服务器端监听的端口发送数据,并由服务器端对该数据进行处理,然后将处理结果返回给客户端. 那么我们在lin ...

  6. java实现服务端守护进程来监听客户端通过上传json文件写数据到hbase中

    1.项目介绍: 由于大数据部门涉及到其他部门将数据传到数据中心,大部分公司采用的方式是用json文件的方式传输,因此就需要编写服务端和客户端的小程序了.而我主要实现服务端的代码,也有相应的客户端的测试 ...

  7. linux下oracle11g R2的启动与关闭监听、数据库

    su - oracle           切换到oracle账户 lsnrctl start          启动监听 sqlplus /nolog     登陆sqlplus conn /as  ...

  8. linux上使用netstat查看当前服务和监听端口

    netstat这个命令常用在网络监控方面.利用这个命令,可以查看当前系统监听的服务和已经建立的服务,以及相应的端口.协议等信息. netstat参数说明 netstat参数虽然很多,但是常用的不多,主 ...

  9. linux下启动多个php,分别监听不同的端口。

    在工作中,我们可能会遇到,服务器集群的搭建. 这个时候,我们不可能,每一台服务器都是lnmp的环境,我们会把nmp分别放在不同的服务器上,不同的服务器负责不同的功能.比如我们下面要说的php 加入ng ...

随机推荐

  1. debug---null Pointer Exception--一步步查找(1)

    找到对应的226行代码: 通过debug打断点,然后选中需要查看的代码,右击,选择Evaluate Expresstion,选择确认,就可以弹出具体的值,发现真的为null. 通过simon帮忙分析, ...

  2. wordcount程序实现与测试

    GitHub地址 https://github.com/jiaxuansun/wordcount PSP表格 PSP PSP阶段 预估耗时(分钟) 实际耗时(分钟) Planning 计划 10 5 ...

  3. TinkerPop中的遍历:图的遍历中谓词、栅栏、范围和Lambda的说明

    关于谓词的注意事项 P是Function<Object,Boolean>形式的谓词.也就是说,给定一些对象,返回true或false.所提供的谓词在下表中概述,并用于各种步骤,例如has( ...

  4. Sublime Text3注册码供研究使用

    文章介绍 看到文章时候感觉不错,一直用的Notepad++.文章属于转载,文末有文章来源,转载注明出处. 一. Sublime 下载地址: Sublime 3: http://www.sublimet ...

  5. 如何使用ArcPy

    ArcPy可以很方便的通过脚本调用ArcGIS的各种函数和功能.在此简单介绍一下.方法包括两种,第一种是直接使用ArcGIS中的命令行,输入一句,执行一句:第二种是创建一个Python脚本,直接执行其 ...

  6. How a web page loads

    The major web browsers load web pages in basically the same way. This process is known as parsing an ...

  7. 关于Lucene,你至少要知道的事

    1.是什么? 全文搜索引擎 2.干什么? 实现网站全文检索功能(自带语法高亮功能) 3.原理? Lucene生成索引(语法解析后,生成索引文件)-根据索引进行查询(语法解析后,根据解析后的结果进行查询 ...

  8. C#校验算法列举

    以下是工作中常用的几种校验算法,后期将不断更新 和校验 /// <summary> /// CS和校验 /// </summary> /// <param name=&q ...

  9. 计算DataTable某列的值(SUM)

    参考,如下:

  10. Eavl整理

    一. 严格模式 eval方法只能在非严格模式中进行使用,在use strict中是不允许使用这个方法的. 二. 用法 eval函数会接收一个参数obj,如果obj不是一个字符串,那么eval会直接返回 ...