1. man解析
O_EXCL
Ensure that this call creates the file:
if this flag is specified in conjunction with O_CREAT,
and pathname already exists, then open() will fail.
When these two flags are specified, symbolic links are not followed:
if pathname is a symbolic link, then open() fails regardless of where the symbolic link points to.
In general, the behavior of O_EXCL is undefined if it is used without O_CREAT.
There is one exception:
on Linux 2.6 and later, O_EXCL can be used without O_CREAT if pathname refers to a block device.
If the block device is in use by the system (e.g., mounted), open() fails with the error EBUSY.
On NFS, O_EXCL is supported only when using NFSv3 or later on kernel 2.6 or later.
In NFS environments where O_EXCL support is not provided,
programs that rely on it for performing locking tasks will contain a race condition.
Portable programs that want to perform atomic file locking using a lockfile,
and need to avoid reliance on NFS support for O_EXCL, can create a unique file on the same filesystem
(e.g., incorpo‐rating hostname and PID), and use link(2) to make a link to the lockfile.
If link(2) returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check
if its link count has increased to 2, in which case the lock is also successful.
2. 用法
同时使用O_CREAT 和 O_EXCL 时,如果文件存在,就返回错误信息(open返回-1,errno是17 ‘EEXIST 17’)。
它可以测试文件是否存在。因为它是原子操作的。
设想这样一个需求:
某个任务要求只能单个进程执行,不能多个进程同时执行。
但实际上不能确保多个进程同时启动,尝试执行这个任务。
这样就进一步要求,只有第一个执行的进程可以继续,后续尝试执行的进程都报错退出。
方案之一就是使用带有O_EXCL标志的open()尝试打开一个文件。
第一个进程执行时文件并不存在,它能成功创建文件并继续执行。
第二个及后续的其它进程会因为文件已存在,从而open()失败,进程退出。
如果不使用O_EXCL标志,那你的代码可能要这样写:
if( access(file, R_OK) == -1 )
open(file, O_RDWR | O_CREAT,0666);
…
这个逻辑是有潜在的问题的,那就是判断文件是否存在与创建文件是两个独立的系统调用。
如果进程1执行access,判断出文件并不存在;
然后由于操作系统的调度策略,进程1暂停执行,进程2执行,进程2也会判断出文件不存在。
最终结果就是:两个进程调用open时都会成功,然后继续执行。这样就有多个进程同时执行这个任务。
因此使用方案一更好。
参考文献:
【1】 http://blog.csdn.net/season_hangzhou/article/details/8472430 作者:Season_hangzhou