Unix系统编程()原子操作和竞争条件

Posted tuhooo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unix系统编程()原子操作和竞争条件相关的知识,希望对你有一定的参考价值。

 

 

竞争状态是这样一种情形:操作共享资源的两个进程(或线程),其结果取决于一个无法预期的顺序,即这些进程获得CPU使用权的先后相对顺序。

以独占的方式创建一个文件

当同时指定了O_EXCL和O_CREAT作为open的标志位时,如果要打开的文件已经存在,则open将返回一个错误。

 

这种机制为了保证进程是打开文件的创建者。

对文件是否存在的检查和创建属于同一原子操作。、

 

如果不实用O_EXCL标志的话,要调用两次open,以此判断文件是否存在,一个是创建一个文件。

但有个情况是:

当第一次调用open时,希望打开的文件还不存在,而当第二次调用open时,其他进程已经创建了该文件。

 

如下图,若内核调度器判断出分配给A进程的时间片已经耗尽,并且将CPU的使用权交给B进程,就有肯能发生这种问题。

 

 

再比如两个进程在一个多CPU系统上同时运行,也会出现这种情况。

在这种情况下,A会认为目标文件是由自己创建的。因为不论目标文件存在与否,进程A对open的第二次调用都会成功。

 

技术分享图片

 

 

由于第一个进程在检查文件是否存在和创建文件之间发生了中断,造成两个进程都声称自己是文件的创建者。

结合O_CREAT和O_EXCL标志来一次性地调用open可以防止这种情况,因为这确保了检查和创建文件的捕捉属于一个单一的原子(不可中断的)操作。

 

向文件尾部追加数据

 

说明原子操作的第二个例子是:多个进程文件同时同一个文件(例如,全局日志文件)尾部添加数据。

每次写入新的日志时,会用lseek将文件偏移量设置到文件尾部,然后再写入数据。

但是在lseek和write之间会被其他进程所打断,那么这两个进程在写入数据前,将文件偏移量设为相同位置,而当第一个进程再次获得调度时,会覆盖第二个进程已写入的数据。此时再次出现了竞争状态,因为执行的结果依赖于内核对两个进程的调度顺序。

 

要规避这一个问题,需要将文件偏移量的移动与数据写入操作纳入同一个原子操作。在打开文件时加入O_APPEND标志就可以保证这一点。

 

注意了,在打开文件时加入O_APPEND标志。所以这个意思就是,打开之后的写都是先移到文件末尾,在写数据咯?

以上是关于Unix系统编程()原子操作和竞争条件的主要内容,如果未能解决你的问题,请参考以下文章

Java并发编程笔记1-竞争条件&初识原子类&可重入锁

java并发编程11.原子变量与非阻塞同步机制

TLPI(liunx/unix系统编程手册)笔记 深入探究文件I/O

《UNIX环境高级编程》笔记——3.文件IO

Unix系统编程概述

Java并发编程