由unix文件I/O引出的原子操作

本文探讨了在Unix系统中,当两个进程并发地对同一文件进行追加写操作时可能出现的问题,以及如何通过原子操作来解决这个问题。文章介绍了原子操作的概念,特别是在多处理器系统中的实现,如x86架构下的`lock`指令和ARM架构下的相关原子操作。还提到了Unix系统提供的`O_APPEND`标志、`pread`和`pwrite`函数以及`O_CREAT`和`O_EXCL`参数如何确保原子性,防止并发问题。
摘要由CSDN通过智能技术生成

第二遍看APUE,打算把知识点总结一下。

问题提出:当两个独立进程A、B同时对一个文件进行追加写操作时(假设这里打开时没有使用O_APPEND参数,即没有从文件尾打开),如果此时进程A调用lseek对该文件偏移量设为100(文件尾),同时内核切换为进程B,B将偏移量也设为100,然后B调用write函数使得B偏移量增加到110。之后内核切换为A,此时如果A调用write的话,还是会从100处开始写入,那么A之前写入的数据会被清除。
这里又涉及到打开文件的内核数据结构:
这里写图片描述
每个进程在进程表中都有一个记录项,其中含有一张文件描述符表,内容如上图。如果两个独立进程各自打开同一个文件,则有下图关系,分别有自己的文件表项(包含文件状态、偏移量等),APUE里讲的比较详细。
这里写图片描述
解决问题的方法是将这两个操作相对于其他进程而言成为原子操作,原子操作是不可分割的操作,在执行完毕时它不会被任何事件中断。
下面介绍一下原子操作:

  • 对于单处理器原子操作
    • 操作可以在一条指令内完成。因为进程的上下文切换是在总是在一条指令执行完成后,所以不会出现上述的并发问题。对于单处理器来说,一条处理器指令就是一个原子操作。
  • 对于多处理器原子操作

    • 在多处理器系统(Symmetric Multi-Processor,简称 SMP)中情况有所不同,由于系统中有多个处理器在独立的运行,即使在能单条指令中完成的操作也可能受到干扰。Intel x86指令集提供了指令前缀lock用于锁定前端串行总线(FSB),保证了指令执行时不会受到其他处理器的干扰。使用lock指令前缀后,处理器间对count内存的并发访问(读/写)被禁止,从而保证了指令的原子性。
      -
  • x86架构处理器原子操作

    • 在linux源码对应体系架构下可以找到原子操作的定义文件atomic.h,里面自加、自减等原子操作。
    • 这里写图片描述
      其中LOCK宏的定义在多处理器架构下,LOCK被定义为lock指令,单处理器架构,LOCK为空,因为此时并不需要 LOCK 指令前缀,处理器只要有可能,原子操作就会被编译成单个机器指令。。
  • ARM架构下原子操作

    • 在对应源码目录下,找到atomic.h,同样也是内嵌汇编代码。
      -这里写图片描述

    回到初始问题,unix系统为其提供了一个原子操作,即open文件时候使用O_APPEND标志,这样使得内核在每次进行写操作之前,都会将偏移量设为文件尾,避免了上述问题

unix系统针对文件I/O还有其他原子操作,例如函数pread和pwrite,调用pread相当于调用lseek后调用read,但是又实现了原子操作,其特点为:

  • 调用pread时,不能中断其定位和读操作,因此其他进程无法将其打断。
  • 不更新当前文件偏移量。

另外还有open函数中的O_CREAT和O_EXCL参数,同时使用这两个参数时,如果文件已经存在,则出错,因此可以用来检查文件是否存在。如果不存在,则创建它,这使得创建和测试成为一个原子操作。如果没有该原子操作的话,下面这段程序可以实现其功能,但是当两个进程同时操作时,还是会出现问题。

if((fd = open(pathname,O_WRONLY)) < 0){
    if(errno == ENOENT){
        if((fd = creat(path,mode)) < 0)
            err_sys("creat error");
    }else 
        err_sys("open error");
}

参考资料:
APUE
http://www.cnblogs.com/fanzhidongyzby/p/3654855.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值