使用 fcntl 模块对文件进行加解锁

简介: 使用 fcntl 模块对文件进行加解锁

当我们在读写文件的时候,如果该文件同时还被另一个进程操作,那么很容易出现混乱。这时候就需要加锁了,正如操作数据库表的时候需要加锁一样。

而 Python 提供了一个库 fcntl,通过 fcntl.flock 函数即可实现对文件进行加锁和解锁。

注意:这个模块目前不支持 Windows,我们只能在类 Unix 下使用。

fcntl.flock 接收两个参数,第一个参数是文件描述符,第二个参数是 operation。常见的 operation 如下:

1)fcntl.LOCK_SH:共享锁,所有进程都可以对当前文件施加共享锁;

2)fcntl.LOCK_EX:排锁,只能有一个进程对当前文件施加排锁,其他进程在施加的时候会阻塞;

3)fcntl.LOCK_UN:对加锁文件进行解锁;

4)fcntl.LOCK_MAND:共享模式强制锁,可以和 LOCK_READ 或者 LOCK_WRITE 联合起来使用,从而表示是否允许并发的读操作或者并发的写操作(基本不用);

5)fcntl.LOCK_NB:非阻塞锁,如果指定此参数,函数不能获得文件锁就立即返回;否则函数会等待获得文件锁,LOCK_NB 可以同 LOCK_SH、LOCK_EX 结合使用;

例如:如果一个文件设置了排他锁

fcntl.flock(f.fileno(), fcntl.LOCK_EX)

那么当其它进程在请求获取这个锁的时候就会一直阻塞在这里。

但如果和 LOCK_NB 结合起来使用:

fcntl.flock(f.fileno(), fcntl.LOCK_EX | fnctl.LOCK_NB)

那么其它进程在获取不到锁的时候就直接返回了。

需要注意的是,在给文件加锁之前,一定要保证文件以相应的访问模式打开。


比如共享锁是让所有进程对文件只有读权限,那么在加共享锁的时候要保证文件以读方式打开;加上排他锁的时候,文件要以可写的形式打开。

下面举例说明,由于 fcntl 不支持 Windows,我们在 Linux 上测试。

41ce3113f4e7569b1c7d04a9778b192c.png

开启一个终端,打开 1.txt 并加上排锁,而一旦施加了排锁,其它进程就不能再加锁了(包括共享锁)。

这里再开启一个终端,测试一下:

835e2e85b278e9accd4f06ff1b05c446.png

进程 1 已经施加了排他锁,进程 2 再加锁的话就会阻塞,不管是共享锁还是排他锁都会阻塞。

9818d5bdac0d68e417c3f0cc1768cfb6.png

然后我们再回到进程 1,将锁释放掉。

c9fc45d5fe7c5b01f3d4c84d94f512fe.png

再来看看进程 2:

2e4474b5b58bfe2397cad8edf3538762.png

此时已经不再阻塞了,因为第一个终端把锁解除了。

我们说设置了排他锁的话,其它进程在获取不到锁的时候会阻塞,但如果和 fcntl.LOCK_NB 结合使用的话,在获取不到锁的时候会直接返回。

进程 1 释放锁之后,已经被进程 2 获取,此时进程 2 给文件施加了排他锁,然后我们继续尝试在进程 1 获取。

6f3a2361d826401977d2c1ce323d1475.png

因为此时获取不到锁,所以直接返回,告诉我们资源不可用。

相关文章
|
Linux C语言
Linux 中的文件锁定命令:flock、fcntl、lockfile、flockfile
Linux 中的文件锁定命令:flock、fcntl、lockfile、flockfile
531 0
|
3月前
|
C++
C/C++静态链接pthread库的坑【-static -pthread】
C/C++静态链接pthread库的坑【-static -pthread】
|
7月前
|
Unix Shell Linux
linux互斥锁(pthread_mutex)知识点总结
linux互斥锁(pthread_mutex)知识点总结
|
Unix Linux
fcntl()函数的作用及用法
fcntl()函数的作用及用法
200 0
|
Shell 开发工具 Android开发
如何确认 fastboot unlock 解锁成功,如何确认DM-verity 已关闭
如何确认 fastboot unlock 解锁成功,如何确认DM-verity 已关闭
1047 0
|
Python
Python:标准库fcntl给打开的文件加锁
Python:标准库fcntl给打开的文件加锁
141 0
Python:标准库fcntl给打开的文件加锁
|
Linux
Linux系统编程-(pthread)线程的使用案例(分离属性、清理函数等)
这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。
215 0
|
存储
【APUE】文件 I/O 操作(一)
【APUE】文件 I/O 操作(一)
221 0
【APUE】文件 I/O 操作(二)
【APUE】文件 I/O 操作(二)
114 0