open函数的O_CREAT与O_EXCL

原创 2015年11月18日 21:32:35

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

相关文章推荐

Unix/Linux下的open函数(O_CREAT和O_EXCL)

open 函数可以打开或创建一个文件。 #include #include #include int open(const char *pathname, int flags); int ope...

open系统调用的O_CREAT和O_EXCL

O_CREAT               If the file does not exist, it will be created.  The owner (user ID) of the f...

open函数中参数选项O_EXCL解析

带O_EXCL参数选项的差别: 第一种: int fd = open(PATH, O_RDWR | O_CREAT, 0666); 当PATH存在时,函数返回值fd为该文件描述符,不存在则创...
  • hjc0321
  • hjc0321
  • 2013年01月14日 11:17
  • 405

带着O_CREAT和O_RDWR进入linux系统调用open函数

首先,linux内核的open函数是这么定义的SYSCALL_DEFINE3(open, ...),可以查到的宏定义为 #define SYSCALL_DEFINE3(name, ...) SYSC...

open中O_EXCL选项的介绍与分析

open的man中的介绍: O_EXCL               Ensure  that  this  call creates the file: if this flag is spe...

open函数中O_CLOEXEC标志的开关

man open里有这么一个flag: O_CLOEXEC (Since Linux 2.6.23)               Enable the close-on-exec flag f...

open函数中O_CLOEXEC标志的开关

http://blog.csdn.net/hiawui/article/details/6211305 CLOEXEC 就是新的内核里的这个选项是把fcntl的这个设置放在open里原子操作,以免在...
  • cjsycyl
  • cjsycyl
  • 2014年03月10日 14:45
  • 5163

文件 I/O——open函数

1.表头文件  #include  2.定义函数 int open( const char * pathname, int oflag);                    int ope...

Linux I/O文件open函数

open函数: 打开或创建一个文件 打开文件成功的描述符一般是从3开始。 简单例子:...

O_EXCL

open系统调用: #include int open(const char *pathname, int oflag, ... /*mode_t mode */ ); 其中,oflag有个可选值...
  • wocjj
  • wocjj
  • 2012年04月04日 12:25
  • 519
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:open函数的O_CREAT与O_EXCL
举报原因:
原因补充:

(最多只允许输入30个字)