精华内容
下载资源
问答
  • 主要介绍了shell脚本实现文件锁功能,本文实现了一个排它锁,从而实现避免脚本重复执行,需要的朋友可以参考下
  • 详解Linux文件锁flock

    2021-01-10 20:12:52
    在多个进程同时操作同一份文件的过程中,很容易导致文件中的数据混乱,需要锁操作来保证数据的完整性,这里介绍的针对文件的锁,称之为“文件锁”-flock。 flock,建议性锁,不具备强制性。一个进程使用flock将文件...
  • 上锁的流程图,利用文件锁和redis,redis存储信息解锁。请结合帖子一起看。帖子是《基于文件锁和redis的方案》
  • 文件锁,锁文件

    2017-12-01 20:31:42
    锁文件,可设置不同用户使用不同的权限,锁文件,可设置不同用户使用不同的权限
  • 在linux下实现守护进程并加上排它锁(文件锁),避免重复启动进程
  • 文件锁 全名叫 advisory file lock, 书中有提及。 这类锁比较常见,例如 mysql, php-fpm 启动之后都会有一个pid文件记录了进程id,这个文件就是文件锁。 这个锁可以防止重复运行一个进程,例如在使用crontab时,限定...
  • golang下文件锁的使用

    千次阅读 2020-12-04 02:38:20
    题目是golang下文件锁的使用,但本文的目的其实是通过golang下的文件锁的使用方法,来一窥文件锁背后的机制。 为什么需要文件锁 只有多线程/多进程这种并发场景下读写文件,才需要加锁, 场景1-读写并发 读写并发...

    前言

    题目是golang下文件锁的使用,但本文的目的其实是通过golang下的文件锁的使用方法,来一窥文件锁背后的机制。

    为什么需要文件锁

    只有多线程/多进程这种并发场景下读写文件,才需要加锁,

    场景1-读写并发

    读写并发场景下,如果不加锁,就会出现读到脏数据的情况。想象一下,读文件的进程,读到第500字节,有其它进程以覆盖写的方式向文件中写入1000字节,那读进程读到的后500字节就是脏数据。

    场景2-写写并发

    写写并发场景下,如果不加锁,假设A进程先写0-1000字节,B进程写0-900字节,以此类推,最后一个进程写0-100字节,那最终的文件内容就是每个进程前100个字节拼接起来的错乱的内容了。

    文件锁的几个概念

    共享锁

    共享锁,也叫读锁。某个进程首次获取共享锁后,会生成一个锁类型的变量L,类型标记为共享锁。其它进程获取读锁的时候,L中的计数器加1,表示又有一个进程获取到了共享锁。这个时候如果有进程来获取排它锁,会获取失败。

    排它锁

    排它锁,也叫写锁。某个进程首次获取排他锁后,会生成一个锁类型的变量L,类型标记为排他锁。其它进程获取任何类型的锁的时候,都会获取失败。

    阻塞

    阻塞的意思是说,新的进程发现当前的文件(数据)被加锁后,会一直处于等待状态,直到锁被释放,才会继续下一步的行为。

    非阻塞

    非阻塞的意思是说,新的进程发现当前的文件(数据)被加锁后,立即返回异常。业务上需要根据具体的业务场景对该异常进行处理。

    阻塞和非阻塞其实是进程遇到锁的时候的两种处理模式。

    golang下如何使用文件锁

    基本使用

    
    package main
    
    import (
        "log"
        "os"
        "syscall"
    )
    
    func main() {
        f, err := os.Create("example.txt")
        if err != nil {
            log.Println("create file example.txt failed", err)
        }
        defer f.Close()
        // 非阻塞模式下,加共享锁
        if err := syscall.Flock(int(f.Fd()), syscall.LOCK_SH|syscall.LOCK_NB); err != nil {
            log.Println("add share lock in no block failed", err)
        }
        // 这里进行业务逻辑
        // TODO
    
        // 解锁
        if err := syscall.Flock(int(f.Fd()), syscall.LOCK_UN); err != nil {
            log.Println("unlock share lock failed", err)
        }
    
        return
    }
    

    示例中 LOCK_SH 表示当前获取的是共享锁,如果是 LOCK_EX,则表示获取的是排他锁。而 LOCK_NB 表示当前获取锁的模式是非阻塞模式,如果需要阻塞模式,不加这个参数即可。LOCK_UN 则表示解锁,即释放锁。

    golang 下这种文件锁的使用方式其实是Linux下的系统级调用,使用的是Linux的原生的文件锁的相关能力。

    使用flock的几个注意点

    1、只要fd指向的是同一个文件指针,那么加锁解锁的行为都是继承和覆盖的(这个可以看最后的解释)。

    2、flock这种方式加的是建议性锁,也就是说新的进程一上来不管三七二十一,不去通过flock获取锁,就对文件各种操作,也是可以正常生效的。

    说一说Linux下面的flock和fcntl

    和flock一样,fcntl也是系统级调用,但是在具体的使用上却有很大不用,并且两种锁互不干扰,用flock加锁,fcntl无法感知,反之也一样。

    建议性锁和强制锁

    flock加的是建议性锁,而fcntl加的是强制性锁。

    建议性锁,本质是一种协议,约定读写操作前都去检查一下该文件是否有被其它进程加锁。如果不遵守该协议,一上来就对文件进行操作,不检查有没有锁,程序执行上是没有任何问题的,能执行成功。

    强制性锁,才更像真正意义上的锁。只要加了锁,其它进程是无法执行非允许的操作的。

    其实一些利用redis做的分布式锁,都是建议性锁。锁机的机制要生效,需要大家共同遵守这个约定才行。

    全局锁和局部锁

    对于一个文件,flock加锁的范围是整个文件内容,而fcntl能对文件的任意部分加锁。

    锁的持有者问题

    flock认为,锁的持有者是文件表(可以理解为文件指针),所以对于fork和dup操作,他们都对应同一个文件指针,所有的操作都会作用到这个文件上。具体表现:

    • A进程加锁,A的子进程进程可以解锁,新的操作会覆盖之前的操作
    • A进程加锁,A进程复制fd,仍然是可以通过新的fd操作文件锁,新的操作会覆盖之前的操作

    fcntl 认为,锁的持有者是进程。加锁和解锁的行为都是跟着进程走,具体表现为:

    • A进程加锁,B进程得等A进程消亡或者解锁才能加锁

    参考

    [1] 被遗忘的桃源——flock 文件锁

    [2] Linux文件锁学习-flock, lockf, fcntl

    原创不易,欢迎关注我的公众号:码农的自由之路

    展开全文
  • 文件锁

    万次阅读 2016-05-26 18:27:01
    文件锁定是多用户、多任务操作系统中一个非常重要的组成部分。程序经常需要共享数据,而这通常是通过文件 来实现的。因此,对于这些程序来说,建立某种控制文件的方式就非常重要了。只有这样,文件才可以通过一种...

          文件锁定是多用户、多任务操作系统中一个非常重要的组成部分。程序经常需要共享数据,而这通常是通过文件

    来实现的。因此,对于这些程序来说,建立某种控制文件的方式就非常重要了。只有这样,文件才可以通过一种安全

    的方式更新,或者说,当一个程序正在对文件进行写操作时,文件就会进入一个暂时状态在这个状态下,如果另外

    一个程序尝试读这个文件,它就会自动停下来等待这个状态的结束。

          Linux提供了多种特性来实现文件锁。其中最简单的方法就是以原子操作方式创建锁文件,所谓"原子操作"就是

    在创建锁文件时,系统将不允许其他的事情发生。这就给程序提供了一种方式来确保它所创建是文件是唯一的,而且

    这个文件不可能被其它程序在同一时刻创建。

    第二种方法更高级一些,它允许程序锁定文件的一部分,从而可以独享对这一部分内容的访问。有这两种不同的方式

    可以实现第二种形式的文件锁定。我们将只对其中的一种做详细介绍,因为两种方式非常相似——第二种方式不过是

    程序接口稍微不同而已。

    一、这些锁文件通常都被放置在一个特定位置,并带有一个与控制资源相关的文件名。例如,当一个调制解调器正在

    被使用时,Linux通常会在/var/spool目录下创建一个锁文件。

    注意:锁文件仅仅只是充当一个指示器的角色,程序间需要通过相互协作来使用它们。

    二、区域锁定

          用创建锁文件的方法来控制对诸如串行口或者不经常访问的文件之类的资源的独占式访问,是一个不错的选择,

    但它并不适用于访问大型的共享文件。假设你有一个大文件,它有一个程序写入数据,但却有许多不同的程序同时

    对这个文件进行更新。当一个程序负责记录长期以来连续收集到的数据,而其他一些程序将一直不停地运行,所以

    它们需要一些协调方法来提供对一个文件的并发访问。可以通过锁定文件区域的方法来解决这个问题,文件中的某

    个特定部分被锁定了,但是其他程序可以访问这个文件中的其它部分。这被称为文件段锁定或文件区域锁定。Linux

    提供了至少两种方式来实现这一功能:它们使用不同的底层实现,因此决不要混合使用这两种类型的调用,而应坚

    持使用其中的一种。

    三、文件锁功能函数

          int fcntl(int fileds, int command, struct flock *flock_structure);

          fcntl对一个打开的文件描述符进行操作,并根据command参数的设置完成不同的任务。

          command参数:F_GETLK、F_SETLK、F_SETLKW;

          flock结构体:short l_type、short l_whence、off_t l_shart、off_t l_len、pid_t l_pid。

          1、F_GETLK:用于获取files(第一个参数)打开的文件的锁信息。它不会尝试去锁定文件。调用进程把自己想创

              建的锁类型信息传递给fcntl,使用F_GETLK命令的fcntl就会返回将会阻止获取锁的任何信息。

              short l_type:如果是共享(只读)锁则取值为F_RDLCK,如果是独占(写)锁则取值为F_WRLCK

              short l_whence:SEEK_SET、SEEK_CUR、SEEK_END中的一个

              off_t l_shart:感兴趣的文件区域的第一个字节的相对位置

              off_t l_len:感兴趣的文件区域的字节数

              pid_t l_pid:持有锁的进程的标识符

                   进程可能使用F_GETLK调用来查看文件中某个区域的当前锁状态。它应该设置flock结构体来表明它需要

              的锁类型,并定义它感兴趣的文件区域。fcntl调用如果成功就返回非-1的值。如果文件已被锁定从而阻止锁

              请求成功执行,fcntl会用相关信息覆盖flock结构。如果锁请求可以成功执行,flock结构将保持不变。如果

              F_GETLK调用无法获得信息,它将返回-1表明失败。如果F_GETLK调用成功,调用程序就必须检查flock结

             构的内容来判断其是否被修改过。因为l_pid的值被设置成持有锁的进程(若有的话)的标识符,多以通过检查这

             个字段就可以很方便地判断出flock结构是否被修改过。

          2、F_SETLK:对files指向的文件的某个区域加锁或解锁。flock结构中使用的值(与F_GETLK命令中用到的不同之

             处)如下:

             l_type:如果是只读或共享锁则取值为F_RDLCK,如果是独占或写锁则取值为F_WRLCK,如果是解锁则取值

                          为F_UNLK

             l_pid:不使用

                  与F_GETLK一样,要加锁的区域由flock结构中的l_start、l_whence和l_en的值定义。如果加锁成功,fcntl

             将返回一个非-1的值;如果失败,则返回-1.这个函数总是立刻返回。

          3、F_SETLKW:与介绍的F_SETLK作用相同,但在无法获取锁时,这个调用将等待直到可以为止。一旦这个调用

              开始等待,只有在可以获取锁或收到一个信号时它才会返回。

          程序对某个文件拥有的所有锁都将在响应的文件描述符被关闭时自动清除。在程序结束时也会自动清除各种锁。

    四、锁定状态下的读写操作

          当对文件区域加锁之后,必须使用底层的read和write调用来访问文件中的数据,而不要使用更高级的fread和

    fwrite调用,这是因为fread和fwrite会对读写的数据进行缓存,所以执行一次fread调用来读取文件中的头100个字节可

    能(事实上,是几乎肯定如此)会读取超过100个字节的数据,并将多余的数据在函数库中进行缓存。如果程序再次使

    用fread来读取下100个字节的数据,它实际上将读取已缓存在函数库中的数据,而不会引发一个底层的read调用来从

    文件中读取更多的数据。

          例1:测试文件上的锁 

                  lock.c -->lock

    #include <unistd.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    
    const char *test_file="test_lock";
    int main(int argc, char *argv[])
    {
    	int file_desc;
    	int byte_count;
    	char *byte_to_write="A";
    	struct flock region_1;
    	struct flock region_2;
    	int res;
    	file_desc=open(test_file,O_RDWR|O_CREAT,0666);
    	if(!file_desc)
    	{
    		fprintf(stderr,"Unable to open %s for read/write\n",test_file);
    		exit(EXIT_FAILURE);
    	}
    	for(byte_count=0;byte_count<100;byte_count++)
    	{
    		write(file_desc,byte_to_write,1);
    	}
    	//把文件的10~30字节设为区域1,并在其上设置共享锁
    	region_1.l_type=F_RDLCK;
    	region_1.l_whence=SEEK_SET;
    	region_1.l_start=10;
    	region_1.l_len=20;
    	//把文件的40~50字节设为区域2,并在其上设置独占锁
    	region_2.l_type=F_WRLCK;
    	region_2.l_whence=SEEK_SET;
    	region_2.l_start=40;
    	region_2.l_len=10;
    	//锁定文件
    	printf("Process %d locking file\n",getpid());
    	res=fcntl(file_desc,F_SETLK,&region_1);
    	if(res==-1)fprintf(stderr,"Failed to lock region_1\n");
    	res=fcntl(file_desc,F_SETLK,&region_2);
    	if(res==-1)fprintf(stderr,"Failed to lock region_2\n");
    
    	sleep(60);
    	printf("Process %d closing file\n",getpid());
    	close(file_desc);
    	exit(EXIT_SUCCESS);
    	
    	return 0;
    }

     

                  lock2.c -->lock2

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    
    const char *test_file="test_lock";
    #define SIZE_TO_TRY 5
    
    void show_lock_info(struct flock *to_show);
    int main(int argc, char *argv[])
    {
    	int file_desc;
    	int res;
    	struct flock region_to_test;
    	int start_byte;
    
    	file_desc=open(test_file,O_RDWR|O_CREAT,0666);
    	if(!file_desc)
    	{
    		fprintf(stderr,"Unable to open %s for read/write",test_file);
    		exit(EXIT_FAILURE);
    	}
    	for(start_byte=0;start_byte<99;start_byte+=SIZE_TO_TRY)
    	{
    		//设置希望测试的文件区域
    		region_to_test.l_type=F_WRLCK;
    		region_to_test.l_whence=SEEK_SET;
    		region_to_test.l_start=start_byte;
    		region_to_test.l_len=SIZE_TO_TRY;
    		region_to_test.l_pid=-1;
    
    		printf("Testing F_WRLCK on region from %d to %d\n",start_byte,start_byte+SIZE_TO_TRY);
    		//测试文件上的锁
    		res=fcntl(file_desc,F_GETLK,&region_to_test);
    		if(res==-1)
    		{
    			fprintf(stderr,"F_GETLK failed\n");
    			exit(EXIT_FAILURE);
    		}
    		if(region_to_test.l_pid!=-1)
    		{
    			printf("Lock would fail. F_GETLK returned:\n");
    			show_lock_info(&region_to_test);	
    		}
    		else
    		{
    			printf("F_WRLCK - Lock would succed\n");
    		}
    		//用共享(读)锁重复测试一次,再次设置希望测试的文件区域
    		region_to_test.l_type=F_RDLCK;
    		region_to_test.l_whence=SEEK_SET;
    		region_to_test.l_start=start_byte;
    		region_to_test.l_len=SIZE_TO_TRY;
    		region_to_test.l_pid=-1;
    		printf("Testing F_RDLCK on region from %d to %d\n",start_byte,start_byte+SIZE_TO_TRY);
    		//再次测试文件上的锁
    		res=fcntl(file_desc,F_GETLK,&region_to_test);
    		if(res==-1)
    		{
    			fprintf(stderr,"F_GETLK faild\n");
    			exit(EXIT_FAILURE);
    		}
    		if(region_to_test.l_pid!=-1)
    		{
    			printf("Lock would fail. F_GETLK returned:\n");
    			show_lock_info(&region_to_test);
    		}
    		else
    		{
    			printf("F_RDLCK - Lock would succeed\n");
    		}
    	}
    	close(file_desc);
    	return 0;
    }
    void show_lock_info(struct flock *to_show)
    {
    	printf("\t l_type %d, ",to_show->l_type);
    	printf("l_whence %d, ",to_show->l_whence);
    	printf("l_start %d, ",(int)to_show->l_start);
    	printf("l_len %d, ",(int)to_show->l_len);
    	printf("l_pid %d\n",to_show->l_pid);
    }
    


           为了测试首先运行./lock &(后台运行),然后运行./lock2

           下面为输出内容:

     

    Testing F_WRLCK on region from 0 to 5
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 0 to 5
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 5 to 10
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 5 to 10
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 10 to 15
    Lock would fail. F_GETLK returned:
    	 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 6448
    Testing F_RDLCK on region from 10 to 15
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 15 to 20
    Lock would fail. F_GETLK returned:
    	 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 6448
    Testing F_RDLCK on region from 15 to 20
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 20 to 25
    Lock would fail. F_GETLK returned:
    	 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 6448
    Testing F_RDLCK on region from 20 to 25
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 25 to 30
    Lock would fail. F_GETLK returned:
    	 l_type 0, l_whence 0, l_start 10, l_len 20, l_pid 6448
    Testing F_RDLCK on region from 25 to 30
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 30 to 35
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 30 to 35
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 35 to 40
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 35 to 40
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 40 to 45
    Lock would fail. F_GETLK returned:
    	 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 6448
    Testing F_RDLCK on region from 40 to 45
    Lock would fail. F_GETLK returned:
    	 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 6448
    Testing F_WRLCK on region from 45 to 50
    Lock would fail. F_GETLK returned:
    	 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 6448
    Testing F_RDLCK on region from 45 to 50
    Lock would fail. F_GETLK returned:
    	 l_type 1, l_whence 0, l_start 40, l_len 10, l_pid 6448
    Testing F_WRLCK on region from 50 to 55
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 50 to 55
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 55 to 60
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 55 to 60
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 60 to 65
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 60 to 65
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 65 to 70
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 65 to 70
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 70 to 75
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 70 to 75
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 75 to 80
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 75 to 80
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 80 to 85
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 80 to 85
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 85 to 90
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 85 to 90
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 90 to 95
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 90 to 95
    F_RDLCK - Lock would succeed
    Testing F_WRLCK on region from 95 to 100
    F_WRLCK - Lock would succed
    Testing F_RDLCK on region from 95 to 100
    F_RDLCK - Lock would succeed


     解析:

           lock2程序把文件中的每5个字节分成一组,为每个组设置一个区域结构来测试锁,然后通过使用这些结构来

    判断对应区域是否可以被加写锁或读锁。返回信息将显示造成锁请求失败的区域字节数和从字节0开始的偏移量。

    因为返回结构中的l_pid元素包含当前拥有文件锁的程序的进程标识符,所以程序先把它设置为-1(一个无效值),然后

    在fcntl调用返回后检测其值是否被修改过。如果该区域当前未被锁定,l_pid的值就不会被改变。

          为了理解程序的输出含义,需要查看程序中包含的头文件fcntl.h(通常是/usr/include/fcntl.h),l_type的值为1对应

    的定义为F_WRLCK:表明锁失败的原因是已经存在一个写锁了,l_type的值为0对应的定义为F_RDLCK:已经存在

    一个读锁了。在文件中未被lock2程序锁定的区域上,无论是共享锁还是独占锁都将会成功。

          可以看到10~30字节上可以设置一个共享锁,因为程序lock2在该区域上设置的是共享锁而不是独占锁。而在

    40~50字节的区域上,两种锁都将失败,因为lock2已经在该区域上设置了一个独占锁(F_WRLCK)。

          例2:文件锁的竞争
                 lock.c -->lock  与上诉代码相同


                 lock3.c -->lock3

    #include <unistd.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <fcntl.h>
    
    const char *test_file="test_lock";
    
    int main(int argc, char *argv[])
    {
    	int file_desc;
    	int res;
    	struct flock region_to_lock;
    
    	file_desc=open(test_file,O_RDWR|O_CREAT,0666);
    	if(!file_desc)
    	{
    		fprintf(stderr,"Unable to open %s for read/write",test_file);
    		exit(EXIT_FAILURE);
    	}
    	//程序的其余部分指定文件的不同区域,并尝试在它们之上执行不同的锁操作
    	region_to_lock.l_type=F_RDLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=10;
    	region_to_lock.l_len=5;
    
    	printf("Process %d,trying F_RDLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLK,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - obtained to lock region\n",getpid());
    	}
    
    	region_to_lock.l_type=F_UNLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=10;
    	region_to_lock.l_len=5;
    
    	printf("Process %d,trying F_UNLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLK,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - unlocked region\n",getpid());
    	}
    
    	region_to_lock.l_type=F_UNLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=0;
    	region_to_lock.l_len=50;
    
    	printf("Process %d,trying F_UNLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLK,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - unlocked region\n",getpid());
    	}
    
    	region_to_lock.l_type=F_WRLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=16;
    	region_to_lock.l_len=5;
    
    	printf("Process %d,trying F_WRLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLK,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - obtained lock on region\n",getpid());
    	}
    	
    	region_to_lock.l_type=F_RDLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=40;
    	region_to_lock.l_len=10;
    
    	printf("Process %d,trying F_RDLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLK,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - obtained lock on region\n",getpid());
    	}
    
    	region_to_lock.l_type=F_WRLCK;
    	region_to_lock.l_whence=SEEK_SET;
    	region_to_lock.l_start=16;
    	region_to_lock.l_len=5;
    
    	printf("Process %d,trying F_WRLCK, region %d to %d\n",getpid(),(int)region_to_lock.l_start,(int)(region_to_lock.l_start+region_to_lock.l_len));
    	res=fcntl(file_desc,F_SETLKW,&region_to_lock);
    	if(res==-1)
    	{
    		printf("Process %d - faild to lock region\n",getpid());
    	}
    	else
    	{
    		printf("Process %d - obtained lock on region\n",getpid());
    	}
    
    	printf("Process %d ending\n",getpid());
    	close(file_desc);
    	exit(EXIT_SUCCESS);
    	return 0;
    }


           为了测试首先运行./lock &(后台运行),然后运行./lock3

          下面为输出内容:
     

    Process 26333,trying F_RDLCK, region 10 to 15
    Process 26333 - obtained to lock region
    Process 26333,trying F_UNLCK, region 10 to 15
    Process 26333 - unlocked region
    Process 26333,trying F_UNLCK, region 0 to 50
    Process 26333 - unlocked region
    Process 26333,trying F_WRLCK, region 16 to 21
    Process 26333 - faild to lock region
    Process 26333,trying F_RDLCK, region 40 to 50
    Process 26333 - faild to lock region
    Process 26333,trying F_WRLCK, region 16 to 21
    
    Process 26323 closing file
    Process 26333 - obtained lock on region
    Process 26333 ending


    解析:

          首先,这个程序尝试试用共享锁来锁定文件中10~15字节的区域。这块区域已被一个共享锁锁定,但共享锁允许

    同时使用,因此加锁成功。然后解除它自己对这块区域的共享锁,这也成功了。接下来,这个程序视图解除这个文件

    前50字节上的锁,虽然它实际上未对这块区域进行锁定,但也成功了,因为虽然这个程序并未对这个区域加锁,但

    解锁请求最终的结果取决于这个程序在文件的头50个字节上并没有设置任何锁。

          这个程序接下来视图用一把独占锁来锁定文件中16~21字节的区域。由于这个区域上已有了一把共享锁,独占锁

    无法创建,因此这个锁定操作失败了。然后,程序又尝试试用一把共享锁来锁定文件中40~59字节的区域。由于这个

    区域上已经有了一把独占锁,因此这个锁定操作也失败了。最后,程序再次尝试在文件中16~21字节的区域上获得一

    把独占锁,但这次它用F_SETLKW命令来等待直到它可以获得一把锁为止。于是程序的输出就会遇到一个很长的停

    顿,直到已锁住这块区域的lock程序因为完成sleep调用、关闭文件而释放了它先前获得的所有锁为止。lock3程序继

    续执行,成功锁定了这块区域,最后它也退出了运行。

     

    展开全文
  • Linux文件锁

    千次阅读 2018-06-28 20:23:01
    一、文件锁的分类: 翻阅参考资料,你会发现文件锁可以进行很多的分类,最常见的主要有读锁与写锁,前者也叫共享锁,后者也叫排斥锁,值得注意的是,多个读锁之间是不会相互干扰的,多个进程可以在同一时刻对同一个...

    一、文件锁的分类:

            翻阅参考资料,你会发现文件锁可以进行很多的分类,最常见的主要有读锁与写锁,前者也叫共享锁,后者也叫排斥锁,值得注意的是,多个读锁之间是不会相互干扰的,多个进程可以在同一时刻对同一个文件加读锁;但是,如果已经有一个进程对该文件加了写锁,那么其他进程则不能对该文件加读锁或者写锁,直到这个进程将写锁释放,因此可以总结为:对于同一个文件而言,它可以同时拥有多个读者,但是在某一时刻,他只能拥有一个写者。

          根据内核行为来分,文件锁可以分成劝告锁强制锁两大类:

          1.  劝告锁:

             劝告锁讲究的是一种协同工作,内核仅负责对文件加锁以及检查文件是否已经上锁等操作,而不亲自去参与文件锁的控制与协调,而这些都需要程序员首先要检查所要访问的文件之前是否已经被其他进程加锁来实现并发控制,劝告锁不仅可以对文件的任一部分加锁,也可以对整个文件加锁。下面是加锁规则:


            2.强制锁:

               强制锁则是内核强制使用的一种文件锁,每当有进程违反锁规则,内核将会进行阻止,具体的加锁规则如下:
               (1)若一个文件已经加上共享锁,那么其他进程在对这个文件进行写操作时将会被内核阻止;
               (2)若一个文件已经加上了排他锁,那么其他进程对这个文件的读取与写操作都将被阻止;
                下表总结了进程试图访问已经加有强制锁的文件,进程行为如下:


               从上表可以看出,若进程要访问文件的锁类型与要进行的操作存在冲突,那么若操作时在阻塞时进行,则进程将会阻塞;若操作时在非阻塞时进程,则进程将会立即返回EAGIN错误(PS:表示资源临时不可达)。
               根据加锁区域范围,可以分成整个文件锁与区域文件锁(记录锁),二者很好区分,前者可以锁定整个文件,而后者则可以锁定文件中的某一区域,甚至是某几个字节。

    二、文件锁相关的系统调用:

                目前跟文件加锁相关的系统调用主要有两个:flock与fcntl, 二者在应用范围方面也存在着一些差别,早起的flock函数只能处理劝告锁,在Linux 2.6版本中将其功能扩充至强制锁,另外flock函数只能对整个文件加锁,不能加记录锁,而fcntl函数则不仅完全支持加劝告锁与强制锁,还支持记录锁,另外因为它符合POSIX标准,具有很好的可移植性

             值得注意的是,在给文件加锁之前,一定要保证文件以相应的访问模式打开,例如要对一个文件加上共享锁,一定要首先按读模式打开文件,若要给文件加上排他锁,则首先要按写模式打开对应文件若想加两种锁,则需要按读写模式打开.

            int fcntl(int fd, int cmdstruct flock*lock)  

            fcntl函数专门用来对文件描述符操作的,具体的操作行为取决于cmd值,与本文文件锁相关的cmd值主要有:

            F_GETLK:获取文件锁

            F_SETLK:设置文件锁(非阻塞版)

            F_SETLKW:设置文件锁(阻塞版)

             值得注意的是,调用F_SETLKW命令去设置文件锁的请求不能完成,则进程将会进入休眠状态,直至所要求的锁被释放。其它更多的cmd值可以参考《UNIX环境高级编程》或者”man fcntl”。

             lock参数主要是用来实现指定文件锁类型、所锁定的文件范围以及正在锁定文件的进程ID(只是在获取文件锁时才会用到),详细结构如下:

    1. struct flock {
    2. short l_type; /* Type of lock: F_RDLCK, F_WRLCK, F_UNLCK */
    3. short l_whence; /* How to interpret l_start: SEEK_SET, SEEK_CUR, SEEK_END */
    4. off_t l_start; /* Starting offset for lock */
    5. off_t l_len; /* Number of bytes to lock */
    6. pid_t l_pid; /* PID of process blocking our lock (F_GETLK only) */
    7. };

            其中l_type定义所的类型,F_RDLCK表示共享锁,F_WRLCK表示排他锁,F_UNLCK表示释放掉之前已经建立的锁;l_whence, l_start与l_len共同作用设置所加锁的范围,其中l_whence设置锁的参照起始点,SEEK_SET表示文件开头,SEEK_CUR表示文件当前位置(fseek可以移动文件指针位置),SEEK_END表示文件结尾;l_start与l_whence相结合确定了锁的绝对起始点,l_len则表示从绝对起始点开始需要锁定的字节数,其值可正可负,锁的范围则是[l_start, l_start+l_len-1],若其值为0,则有特殊的含义,表示锁的区域从绝对起始点开始到最大可能的偏移量为止,这种情况可用于锁定整个文件,此时只需将锁的绝对起始点设置为文件开始位置即可。

             函数的返回值是:若成功则返回0,否则返回-1.

             int flock(int fd, int operation)

             相对于fcntl函数,flock显得更加简单,因为所加的锁会影响整个文件,其中operation参数规定了所加锁的类型:

             LOCK_SH:表示加共享锁

             LOCK_EX:表示排他锁

             LOCK_UN:表示释放锁

             LOCK_MAND:表示强制锁

    三、锁的继承与释放:

           1.      锁与进程和文件紧密相连,若进程终止,则有它创建的所有锁将会自动释放掉;若关闭文件描述符,则进程由此描述符引用的文件上的任何锁也将会被释放

           2.      由fork产生的子进程不会继承父进程的文件锁;

           3.      在执行exec之后,新程序可以继承原来程序的文件锁。


    跟锁有关的封装函数(来自于《高级UNIX环境编程》如下测试例子:

    1. /***************************************file_lock.h*******************************************/
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <unistd.h>
    5. #include <string.h>
    6. #include <errno.h>
    7. #include <fcntl.h>
    8. #include <signal.h>
    9. #include <sys/types.h>
    10. #include <sys/stat.h>
    11. int lock_reg(int, int, int, off_t, int, off_t); //register lock
    12. pid_t lock_test(int, int, off_t, int, off_t); //test lockable
    13. //set lock
    14. #define read_lock(fd, offset, whence, len) \
    15. lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))
    16. #define readw_lock(fd, offset, whence, len) \
    17. lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))
    18. #define write_lock(fd, offset, whence, len) \
    19. lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))
    20. #define writew_lock(fd, offset, whence, len) \
    21. lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))
    22. #define un_lock(fd, offset, whence, len) \
    23. lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))
    24. //Test lock
    25. #define read_lock_pid(fd, offset, whence, len) \
    26. lock_test((fd), F_RDLCK, (offset), (whence), (len))
    27. #define write_lock_pid(fd, offset, whence, len) \
    28. lock_test((fd), F_WRLCK, (offset), (whence), (len))
    29. #define is_read_lockable(fd, offset, whence, len) \
    30. (read_lock_pid == 0)
    31. #define is_write_lockable(fd, offset, whence, len) \
    32. (write_lock_pid == 0)
    1. /******************************************file_lock.c****************************************/
    2. #include "file_lock.h"
    3. int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
    4. {
    5. struct flock lock;
    6. lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */
    7. lock.l_start = offset; /* byte offset, relative to l_whence */
    8. lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
    9. lock.l_len = len; /* #bytes (0 means to EOF) */
    10. return(fcntl(fd, cmd, &lock));
    11. }
    12. pid_t lock_test(int fd, int type, off_t offset, int whence, off_t len)
    13. {
    14. struct flock lock;
    15. lock.l_type = type; /* F_RDLCK or F_WRLCK */
    16. lock.l_start = offset; /* byte offset, relative to l_whence */
    17. lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */
    18. lock.l_len = len; /* #bytes (0 means to EOF) */
    19. if (fcntl(fd, F_GETLK, &lock) < 0)
    20. {
    21. printf("fcntl error for %s.\n", strerror(errno));
    22. return (-1);
    23. }
    24. if (lock.l_type == F_UNLCK)
    25. {
    26. return(0); /* false, region isn't locked by another proc */
    27. }
    28. return(lock.l_pid); /* true, return pid of lock owner */
    29. }
    1. /*****************************************file_lock.c*****************************************/
    2. #include "file_lock.h"
    3. static void lock_set(int fd, int type) ;
    4. int main(int argc, char **argv)
    5. {
    6. int fd ;
    7. //First open file and choose right mode by lock type
    8. fd = open("/tmp/hello", O_RDWR | O_CREAT, 0666) ;
    9. if (fd < 0)
    10. {
    11. printf("open error ! \n") ;
    12. exit(1) ;
    13. }
    14. //lock
    15. printf("press ENTER to add lock:\n");
    16. getchar() ;
    17. lock_set(fd, F_WRLCK) ;
    18. printf("press ENTER and exit, lock release:\n");
    19. getchar() ;
    20. //release lock
    21. lock_set(fd, F_UNLCK) ; //useless code, lock release if close fd
    22. if (close(fd) < 0)
    23. {
    24. printf("\n close file error ! \n") ;
    25. exit(1) ;
    26. }
    27. return 0 ;
    28. }
    29. void lock_set(int fd, int type)
    30. {
    31. pid_t read_lock_id = 0;
    32. pid_t write_lock_id = 0;
    33. while (1)
    34. {
    35. //set lock according to lock type
    36. switch (type)
    37. {
    38. case F_RDLCK:
    39. if (read_lock(fd, 0, SEEK_SET, 0) == 0)
    40. {
    41. printf("read lock set by %d \n", getpid());
    42. return;
    43. }
    44. break;
    45. case F_WRLCK:
    46. if (write_lock(fd, 0, SEEK_SET, 0) == 0)
    47. {
    48. printf("write lock set by %d \n", getpid());
    49. return;
    50. }
    51. break;
    52. case F_UNLCK:
    53. if (un_lock(fd, 0, SEEK_SET, 0) == 0)
    54. {
    55. printf("release lock by %d \n", getpid());
    56. return;
    57. }
    58. break;
    59. }
    60. //test lock owner
    61. if (type == F_RDLCK)
    62. {
    63. if ((read_lock_id = read_lock_pid(fd, 0, SEEK_SET, 0)) != 0)
    64. {
    65. printf("read lock already set by %d \n", read_lock_id);
    66. }
    67. }
    68. else if (type == F_WRLCK)
    69. {
    70. if ((write_lock_id = read_lock_pid(fd, 0, SEEK_SET, 0)) != 0)
    71. {
    72. printf("write lock already set by %d \n", write_lock_id);
    73. }
    74. }
    75. }
    76. }
    1. /****************************************Makefile*********************************************/
    2. all: file_lock_test
    3. CC = gcc
    4. file_lock_test:
    5. $(CC) file_syn.c file_lock.c -o file_lock_test
    6. clean:
    7. rm -rf *.o file_lock_test

    
    

    摘自:https://blog.csdn.net/dragon_li_chen/article/details/17147911

    展开全文
  • 文件锁的使用浅析

    万次阅读 2018-04-22 22:27:23
    概述 ...文件锁(也叫记录锁)的作用是,当一个进程读写文件的某部分时,其他进程就无法修改同一文件区域。 能够实现文件锁的函数主要有2个:flock和fcntl。 早期的伯克利版本只支持flock,该...

    概述

    在多数unix系统中,当多个进程/线程同时编辑一个文件时,该文件的最后状态取决于最后一个写该文件的进程。

    对于有些应用程序,如数据库,各个进程需要保证它正在单独地写一个文件。这时就要用到文件锁。

    文件锁(也叫记录锁)的作用是,当一个进程读写文件的某部分时,其他进程就无法修改同一文件区域。

    能够实现文件锁的函数主要有2个:flockfcntl

    早期的伯克利版本只支持flock,该函数只能对整个文件加锁,不能对文件的一部分加锁。

    lockf是在fcntl基础上构造的函数,它提供了一个简化的接口。它们允许对文件中任意字节区域加锁,短至一个字节,长至整个文件。


    fcntl函数

    #include <fcntl.h>
    
    int fcntl(int fd, int cmd, .../*struct flock *flockptr*/);
    #返回值:若成功,返回值依赖于cmd,失败返回-1

    cmdF_GETLK, F_SETLK, F_SETLKW中的一个。第三个参数是指向flock结构的指针,flock结构如下:

    struct flock {
    short l_type;/* one of F_RDLCK, F_WRLCK, F_UNLCK */
    short l_whence;/* SEEK_SET, SEEK_CUR, SEEK_END */
    off_t l_start;/* offset in bytes, relative to l_whence */
    off_t l_end;/* length, in bytes, 0 means lock to EOF */
    off_t l_pid;/* returned with F_GETLK */
    };

    其中,

    • 锁类型:共享读锁F_RDLCK,独占性写锁F_WRLCK,解锁F_UNLCK
    • 加锁或解锁区域的起始字节偏移量(l_start, l_whence
    • 区域字节长度(L_len
    • 进程的id持有的锁能阻塞当前进程,仅由F_GETLK返回
    • 锁可以在文件尾处开始或者越过尾端开始,但是不能在文件起始位置之前开始
    • l_len=0, 表示锁的范围可以扩大到最大可能偏移量,这意味着不管向文件中追加多少数据,它们都可以处于锁的范围内,而且起始位置可以任意
    • 设置l_startl_whence指向文件的起始位置,并且指定l_len=0,以实现对整个文件加锁(一般l_start=0, l_whence=SEEK_SET

    锁的使用

    使用锁的基本规则:

    • 任意多个进程在一个给定的字节上可以有一把共享的读锁(F_RDLCK),但是在一个给定的字节上只能有一个进程有一把独占性写锁(F_WRLCK
    • 如果在一个给定字节上已经有一把或多把读锁,则不能在该字节上再加写锁,如果在一个字节上已经有一把独占性写锁,则不能再对它加任何读锁
    • 对于单个进程而言,如果进程对某个文件区域已经有了一把锁,然后又试图在相同区域再加一把锁,则新锁会替换旧锁
    • 加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开

    fcntl三种cmd的使用:

    • F_GETLK:判断由flockptr所描述的锁是否会被另一把锁所排斥(阻塞),如果存在一把锁阻止创建由flockptr所描述的锁,由该现有锁的信息将重写flockptr指向的信息。如果不存在这种情况,则除了将l_type设置为F_UNLCK之处,flockptr所指向结构中的其他信息保持不变
    • F_SETLK:设置由flockptr所描述的锁,如果程序试图获得一把锁,而系统阻止程序获得该锁,则fcntl会立即返回错误,errno设置为EACCES或EAGAIN。当l_type=F_UNLCK时,此命令用来清除指定的锁
    • F_SETLKW:F_SETLK的阻塞版本(wait)。如果程序尝试获得的锁无法被授予,调用进程会进入休眠直到进程获得锁或者信号中断

    注意:用F_GETLK 测试能否创建一把锁,然后用F_SETLK尝试建立锁之间并非原子操作,也就是说两次调用之间有可能另一进程插入并创建了相同的锁。如果不希望在等待锁变为可用时产生阻塞,就必须处理由F_SETLK返回的可能出错值

    下面是测试一把锁的例子:

    #include <stdio.h>
    #include <errno.h>
    #include <pthread.h>
    #include <fcntl.h>
    
    pid_t lock_test(int fd, 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;
        l   ock.l_len = len;
    
        if (fcntl(fd, F_GETLK, &lock) < 0) {
            printf("fcntl error: %s\n", strerror(errno));
            return 1;
        }
    
        if (lock.l_type == F_UNLCK) {
            return 0;
        }
    
        return lock.l_pid;
    }

    锁的继承与释放

    锁的继承和释放有以下三条原则:

    • 锁与进程和文件两者相关联。即当一个进程终止时,它所建立的所有锁均释放,对于描述符而言,无论它何时关闭,进程通过它引用的文件上的任何一把锁也都会释放
    • fork产生的子进程不继承父进程所设置的锁
    • 执行exec后,新程序可以继承原程序的锁。注意,如果对一个文件描述符设置了执行时关闭标志,那么当作为exec的一部分关闭该文件描述符时,将释放相应文件的所有锁

    避免死锁

    如果两个进程互相等待对方持有并且不释放的资源时,这两个进程就会进入死锁状态。

    如果一个进程已经控制了文件中的一个加锁区域,然后它又试图对另一个进程控制的区域加锁,那么它就会进入睡眠,并有可能发生死锁。

    检测到死锁时,内核必须选择一个进程接收错误返回。


    总结

    在多进程或多线程环境中,当多个应用需要读写同一个文件时,需要考虑对文件加锁,以保证对文件修改的一致性。

    在使用文件锁时,应明确应用模式,防止死锁。

    更多关于文件锁的使用细节,请参考《UNIX环境高级编程》。

    展开全文
  • Linux文件---文件锁

    千次阅读 2017-09-02 17:03:12
    通过之前的open()/close()/read()/write()/...当某进程在更新文件内数据时,期望某种机制能防止多个进程同时更新文件从而导致数据丢失,或者防止文件内容在未更新完毕时被读取并引发后续问题,这种机制就是“文件锁”。
  • 文件锁和记录锁

    千次阅读 2018-07-13 10:21:55
    http://blog.chinaunix.net/uid-23634108-id-2393492.html 下面介绍两种两种Linux下对文件加锁的两种方式一、文件锁思想:假设有一个文件A。创建一个加锁文件B,通过不同的进程互斥的访问此加锁文件B达到互斥的访问...
  • php文件锁解决高并发

    千次阅读 2018-03-26 19:33:53
    php文件锁解决高并发 新建一个.txt文件,文件中什么都不用写。 【一】.阻塞(等待)模式:(只要有其他进程已经加锁文件,当前进程会一直等其他进程解锁文件) &lt;?php //连接数据库 $con=mysqli_connect("...
  • 上午在看UNP卷二这一节的时候及其想睡觉,就草草了事,夜晚没有事情干,就来找找博客看看这两个到底是怎么回事吧! 参考文章:https://www.ibm.com/developerworks/cn/linux/l-cn-filelock/index.html 背景知识:...
  • SQLite3 文件锁和并发

    千次阅读 2018-09-06 10:12:49
    SQLite3 文件锁和并发 原文地址 1.0 SQLite3的文件锁及并发 SQLite Version 3.0.0介绍了一种新的锁和日志机制,为了提升SQLite 2的并发性,以及减少“写饥饿”的问题。新机制还允许涉及多数据库文件的事务原子...
  • 小何讲Linux: 文件锁及其实例

    千次阅读 2017-12-04 15:30:07
    1. 文件锁基本概念 Linux中软件、硬件资源都...文件锁是用于解决资源的共享使用的一种机制:当多个用户需要共享一个文件时,Linux通常采用的方法是给文件上锁,来避免共享的资源产生竞争的状态。 文件锁包括建议
  • c#文件锁的实现

    千次阅读 2018-06-02 21:41:58
    大致功能是,启动 文件锁 程序后,将想要上锁的文件或文件夹拖入到加密区,实现对 文件或文件夹 的加密,或者点击浏览文件夹 选择自己想要加密的文件或文件夹。1&gt;效果: 2&gt;对文件或文件夹上锁的原理...
  • 被遗忘的桃源——flock 文件锁

    千次阅读 多人点赞 2017-01-18 23:00:26
    文件锁 flock 共享锁与排他锁 阻塞与非阻塞 flock 实现细节 调用dup forkexecve 时的文件锁 使用 dup 复制文件描述符 通过 fork 产生子进程 子进程重复加锁 execve 函数族中的文件锁 文件锁的解除 用 LOCK_UN 解锁 ...
  • PHP 文件并发操作(文件锁

    千次阅读 2018-03-30 16:24:57
    当需要一个脚本操作而需要阻塞另外的脚本操作时,需要用到文件锁。 锁操作流程: 先加锁,检测锁是否加成功,如果成功再使用! 锁定类型: 读锁: s-Lock(share-lock)共享锁,读操作前,期望增加的锁定。...
  • 文件锁的本质核心和原理

    万次阅读 2018-06-05 09:27:47
    其中说明了flock 是与打开文件文件表项相关联的。根据《Unix 环境高级编程》对打开文件的介绍,打开的文件在进程表和操作系统中的对应的结构如下图所示:每个进程在进程表中都一个对应的项目,叫做进程表项,上图...
  • PHP文件锁同步实例

    千次阅读 2016-11-29 10:34:46
    文件锁达到的效果是: PHP语言中:多个请求,在同一时间段内,访问同一段代码,改代码只能同时处理一个请求,其它的请求排队等候,等一个请求处理完后,再依次处理剩余的请求。 类似于Java的synchronized线程同步...
  • 浅谈PHP利用文件锁处理高并发

    千次阅读 2020-01-19 09:15:16
    在解决高并发的情景下,我们除了使用Redis缓存来实现外,利用文件锁也是一种常常使用的方法,下面介绍PHP是如何使用flock()函数对文件进行加锁,从而解决高并发的情况的。 1.flock函数的介绍 flock有三个参数分别是...
  • Python的文件锁使用

    千次阅读 2017-12-07 11:28:42
    这就要用到文件锁了。关于文件锁的的知识,需要参考UNIX环境编程,这里只简要介绍概念。python的文件锁目前使用的是fcntl这个库,它实际上为 Unix上的ioctl,flock和fcntl 函数提供了一个接口。python通过调用fcntl....
  • 线程锁/进程锁/文件锁

    千次阅读 2017-12-19 11:06:38
    线程锁/进程锁/文件锁  1.线程锁是锁线程的,锁住禁用,如果4线程的CPU锁一个线程剩余三个(如果可以锁的话),就像四车道封锁一条车道还剩3个车道可以跑车;  2.进程锁是锁进程的,进程就是正在运行的程序,锁住...
  • linux文件锁

    千次阅读 2014-11-20 11:06:43
    第一节Unix支持的文件锁技术介绍 Unix系统允许多个进程同时对一个文件进行读写,虽然每一个read或write调用本身是原子的,但内核在两个读写操作之间并没有加以同步,因此当一个进程多次调用read来读文件时,其它...
  • 锁——FileLock 文件锁

    千次阅读 2018-07-25 14:55:19
    文件锁(FileLock),使用文件锁锁住文件后,其他进程不能操作读或写文件,除非当前进程release或unlock文件锁。 前两天看码云上的oim项目源码,该项目即使用了文件锁来防止同一账户重复登录(当然,该方法是不太...
  • Linux记录锁(文件锁

    千次阅读 2018-09-24 09:37:04
    当第一个进程正在读或修改文件的某个部分时,使用记录可以阻止其他进程修改同一文件区。 “记录”这个词是一种误用,因为UNIX系统内核根本没有使用文件记录这种概念。 一个更适合的术语可能是字节范围 (byte-...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 541,539
精华内容 216,615
关键字:

文件锁