1、文件的管理
1.1 使用fcntl()实现建议/文件锁的功能
(1)建议锁/文件锁的由来
当两个进程在同一时刻向同一个文件中写入数据时,可能造成数据的交错和不一致问题;
当一个进程在向文件中写入数据的同时,另外一个进程读取文件中数据时可能造成数据的不一致性问题;
当两个进程同时读取同一个文件数据时,可以同时进行;
没有读写操作 | 读取操作 | 写入操作 | |
读取 | ok | ok | no |
写入 | ok | no | no |
为了实现上述表格的效果,linux系统中引入了文件锁的机制,文件锁本质上就是读写锁,一把读锁和一把写锁,其中读锁是一把共享锁,允许其他进程加读锁,但不能加写锁;写锁是一把排它锁,不允许其它进程加读锁/写锁(君子协定)。
(2)使用F_SETLK作为函数实参的用法
当锁的类型是:F_RDLCK
| F_WRLCK
时,实现加锁效果;
当锁的类型是:F_UNLCK
时,实现解锁效果;
具体的锁信息由该函数的第三个参数来指定;
当文件上已经拥有冲突锁时,该函数调用失败,返回-1并设置errno的数值;
当前区域无任何锁 | 当前区域有读锁 | 当前区域有写锁 | |
加读锁 | ok | ok | no |
加写锁 | ok | no | no |
由程序结果可知:
当文件被放置文件锁之后,数据还是可以写入到文件的,也就是说文件锁并不能控制其他进程的读写操作,但是文件锁可以控制其他进程是否加锁成功(两个读锁除外)
思考:
如何实现文件锁对其他进程读写操作的控制呢???
解决方案:
一般来说,每次进行读写操作之前可以先尝试加读写锁,如果读写锁能够加上,则进行读写操作,如果读写锁不能加上,则放弃读写操作,从而实现上述效果;
释放锁的主要方式:
a. 将锁的类型设置为F_UNLCK
,使用fcntl()
调用即可;
b. 使用close()
关闭文件描述符时,与该描述符有关的文件锁全部被自动释放;
c. 当进程结束时,与该进程有关的文件锁全部被释放;
(3)使用F_SETLKW作为函数实参的用法
功能与F_SETLK
类似,所不同的是当文件上已经拥有冲突的锁信息时,该函数调用并不会返回失败,而是一直等待直到文件上存在的锁被释放为止;
(4)使用F_GETLK作为函数实参的用法
调用fcntl()的第三个实参是描述要放置在文件上的锁信息,如果该锁能够被放在文件上,则不会真正地去放置,只是将锁的类型改为F_UNLCK
,结构体其他成员保持不变;
如果该锁不能被放置在文件上,则fcntl()
会用文件上已经存在的锁信息去替换第三个参数描述的锁信息,并将l_pid
的数值设置为真正给文件加锁进程的进程号;
注意:
一般来说,为了避免和其他进程同时进行读写操作,在每次进行读写操作之前尝试加读写锁,如果成功放置读写锁时,则进行读写操作,在执行完毕读写操作之后,再释放读写锁;如果不能成功放置读写锁,则主动放弃读写操作;
1.2 access()
#include <unistd.h>
int access(const char *pathname, int mode);
-
参数:
-
*pathname
:字符串形式的文件路径名;
mode
:具体的操作模式;
F_OK
- 判断文件是否存在
R_OK
- 判断文件是否可读
W_OK
- 判断文件是否可写
X_OK
- 判断文件是否可执行
功能:
- 主要用于检查文件的存在性以及是否拥有对应的权限; 练习:
-
查询和尝试使用
stat()
;
明日预报:
-
(1)文件的管理
(2)目录的管理
(3)进程的管理