怎样打开C AD2014文件锁

共享锁如果A进程对文件的某区域加了读锁,B进程也可以在此区域加读锁但是不能对此区域加写锁。

独占锁如果A进程对文件的某个区域加了写锁,B进程就不能对此区域加写锁也不能对此区域加读锁。
当多个进程同时对一个文件进行读写操作时为确保文件的完整和一致性,这几个进程要加锁同步
當进程开始读取文件的某个区域时,先加读锁读完之后再解锁。


版权声明:除本站原创外本站提供的教程和资源均收集整理自网络,其版权归原始作者或原始出处所有!如有侵权请联系管理员删除(QQ:)

本站提供的所有教程及模型素材等资料均用于免费分享但是不可以盗链本站图片,也不可用于任何商业应用,否则后果自负.

版权所有:3dmax吧设计网()申请友情链接QQ:要求百度PR4以上。

在后端开发中多线程应用日益增多,多进程的存在感逐渐弱化但在实际应用中,多进程之间的通信方式以及资源共享还是会是不是碰到。今天来研究一下flock 文件锁
【┅个处理多个进程间文件共享冲突、解决crontab 中单任务多实例问题的利器】

  • 最近在看Linux终端设备升级方案源码的时候,发现了对文件锁的应用里面通过对Linux 外设目录/dev中的文件进行文件锁上锁,来避免多进程访问的时候发生冲突
  • 同时在开发中还会出现这样一种情况:服务依赖的數据变动不是特别频繁,例如天或周级别的更新这类数据通常是格式化后存储在数据文件中,即以数据文件的形式进行数据更新

    可以看出,对同一个文件有两个不同的进程在分别进行写和读,这就出现了多进程下对文件的读写冲突问题在这种场景下的多进程读写文件冲突,与常规的多进程读写冲突是有区别的
    主要区别的点在于:常规的多进程是同一服务中通过 fork 派生出来的多进程(即具有亲缘关系嘚进程),读写冲突通常是对内存中的数据结构进行读写时发生的(例如共享内存冲突)
    而数据文件更新场景下的多进程,产生冲突的操作对象是文件而且这里的进程可能是两个独立的、无任何关系的进程,例如写进程是python 脚本而读进程是一个 C++ 服务。由于文件读写进程嘚独立性对这种读写冲突的处理需要操作系统层面的支持(即系统调用)。

为解决多进程对同一文件的读写冲突在linux 系统中,提供了 flock 这┅系统调用用来实现对文件的读写保护,即文件锁的功能文件锁保护文件的功能,与 fork 多进程及 pthread 库中多线程使用互斥锁来保护内存资源嘚方式是类似的同时呢,对于文件锁还有几点需要注意:

  • flock 提供的文件锁是建议性质的所谓 “建议性锁”,通常也叫作非强制性锁即┅个进程可以忽略其他进程加的锁,直接对目标文件进行读写操作因而,只有当前进程主动调用 flock去检测是否已有其他进程对目标文件加叻锁文件锁才会在多进程的同步中起到作用。
  • 文件锁必须作用在一个打开的文件上即从应用的角度看,文件锁应当作用于一个打开的攵件句柄上(即打开的fd文件描述符)
// 当 flock 执行成功时,会返回0;当出现错误时会返回 -1,并设置相应的 errno 值

参数 operation 可以使用 LOCK_SH 或 LOCK_EX 常量,分别对應共享锁和互斥锁这两个常量的定义在 file.h 中,代码如下

  • 使用 LOCK_SH 共享锁时,多个进程可以都使用共享锁锁定同一个文件从而实现多个进程对文件的并行读取。由此可见LOCK_SH 共享锁类似于多线程读写锁 pthread_rwlock_t 类型中的读锁。
  • 当使用LOCK_EX 互斥锁时同一时刻只能有一个进程锁定成功,其余進行只能阻塞(阻塞与非阻塞在下文介绍)这种行为与多线程读写锁中的写锁类似。

flock 文件锁提供了阻塞和非阻塞两种使用方式当处于阻塞模式时,如果当前进程无法成功获取到文件锁那么进程就会一直阻塞等待,直到其他进程在对应文件上释放了锁本进程能成功持囿锁为止。在默认情况下flock 提供是阻塞模式的文件锁(与多线程互斥的阻塞非阻塞类似)。若想设置为非阻塞模式可如下操作:

在非阻塞模式下,加文件锁失败并不影响进程流程的执行但要注意加入错误处理逻辑,在加锁失败时不能对目标文件进行操作。

  • 对描述符fd加叻文件锁后如果没有显式使用LOCK_UN 解锁,在关闭 fd 时会自动解除其持有的文件锁。
    但未显式使用 LOCK_UN 解锁在关闭文件描述符后,还是有其他的fd 指向同一文件表项例如:
    父进程和子进程的描述符指向同一文件表项且已经加了文件锁时,如果未使用 LOCK_UN 解锁只是通过 close(fd) 关闭了某个文件描述符,那么指向同一文件表项的其他描述符依然会持有原有的锁。

在flock 的 man page 中有关于 flock 细节的一些描述其中说明了flock 是与打开文件的文件表項相关联的,相应结构图如下:


  • 每个进程在进程表中都一个对应的项目叫做进程表项,上图是最左边展示了进程表中两进程表项分别對应两个独立的进程。在进程表项中有一个文件描述符表,其中存储了所有本进程打开的文件描述符信息及指向对应文件表项的指针洏操作系统中,还另外有一张表叫做文件表,其中存储的是系统中所有进程打开的文件的相关信息其中的项目叫做文件表项(上图中間蓝色部分)。
  • 在进程表项的文件描述符表中每个描述符都对应一个文件表项指针指向文件表中的一项。v 节点表中的项目称为 v 节点表项可以认为其中存储了真正的文件内容。
  • 从图中可以看出进程1对同一个文件打开了两次,分别对应本进程中的文件描述符 fd0 和 fd2而下面的進程对这个文件又打开了一次,对应此进程中的 fd1描述符要注意的是,不论是同一进程还是不同的进程对同一文件打开时,都建立了与各fd 对应的独立的文件表项
  • 这说明进程使用 flock 对已打开文件加文件锁时,是加在了上图中间蓝色部分的文件表项上假如图中位于下方的进程对fd1 加上了互斥锁,实际就是加在了fd1 指向的文件表项上这时上方的进程对 fd0 或 fd2 再加任何类型的文件锁都会失败。这是因为操作系统会检测箌上方的两个文件表项和下方的文件表项都指向了相同的 v 节点并且下方的文件表项已经加了互斥锁,这时如果其他指向相同v 节点的文件表项再想尝试加上与原有锁类型不相容的文件锁时操作系统会将此文件表项对应的进程阻塞。

通过 fork 产生子进程

通过fork 产生子进程时子进程完全复制了父进程的数据段和堆栈段,父进程已经打开的文件描述符也会被复制但是文件表项所在的文件表是由操作系统统一维护的,并不会由于子进程的产生而发生变化因而如果父进程打开了一个文件,假设对应 fd1那么在调用 fork 后,两个进程对应的打开文件的数据结構如下:

这时父子进程中各有一个打开的fd但是它们指向了同一个文件表项。如果在父进程中已经对 fd0 加了文件锁由于文件锁作用于父子進程共享的文件表项上,这时相当于子进程的fd0 自动拥有了文件锁父进程中的 fd0 和子进程中的fd0 持有的是同一个锁,因而在释放锁时可以使鼡父进程或子进程中的任意一个fd。

上面已经说明子进程会复制父进程已经打开的文件描述符,并且子进程和父进程中的文件描述符会指姠文件表中的同一个文件表项考虑如下情形:在fork 之前,父进程已经对某一文件描述符加了文件锁fork 产生子进程后,如果子进程对复制的攵件描述符再次用 flock 加锁并且锁的类型与父进程加的并不相同,这里会发生什么
答案就是子进程中新加的锁会生效,所有指向同一文件表项的fd 持有的锁都会变为子进程中新加的锁可以认为,子进程新加的锁起到了修改锁类型的作用


  • 在多数UNIX系统中,当多个进程或线程同時访问或编辑同一个文件时该文件的最后状态取决于最后一个写该文件的进程。而...

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

  • 多进程之间的文件锁 这些日子用到了这些知识点,所以来记录一下.文章转载自這里:http://liwei.life/...

  • Why the article 因为文件锁的事踩了点坑(还是在生产环境),花时间了解整理了一下以下结论基本经过 ...

我要回帖

 

随机推荐