文件IO的原子操作

设计多个进程共同操作一个文件的,就需要原子的操作下面几个问题:

1.添加至一个文件

多个进程都要添加数据到一个文件的尾端

if(lseek(fd,0,SEEK_END)>=0)

{

    write(fd,buff,100);

}

对单个进程而言,这个程序能正常工作,若多个进程同时调用,则会出现问题。

每个进程都有它自己的文件表项,但共享同一个i节点。假定A进程调用lseek,它将A进程的该文件当前偏移量设置到1500字节,然后内核切换,使进程B执行,B调用lseek把当前偏移量便宜到1500字节处,写入了100个字节,文件偏移量到1600字节处,文件长度增加,所有i节点中的当前文件长度更新为1600,然后,内核又切换到A进程运行,A调用write就从当前文件偏移量处(1500)写入文件,这样就覆盖了进程B刚写入的数据。

问题出在“定位到文件尾端,然后写”上,它使用了两个分开的函数调用,解决办法是使这两个分开的操作原子执行,不允许在执行完第一个函数的时候执行内核调度。

unix提供了一种方法,就是打开文件时设置O_APPEND标志。

2.pread和pwrite函数

SUS包括了XSI扩展,允许原子性的定位搜索(seek)和执行IO

#include<unistd.h>

ssize_t pread(int fileds, void* buf, size_t nbytes, off_t offset);

ssize_t pwrite(int fileds, void* buf, size_t nbytes, off_t offset);

pread相当于原子调用lseek和read

pwrite相当于原子调用lseek和write

3.创建一个文件

if ((fd = open(pathname, O_WRONLY)) < 0)

{

    if (errno == ENOENT)

    {

         fd = creat(pathname, mode);

    }

}

如果在open和creat之间,另一个进程创建了该文件,就会引起问题。例如,另一个进程创建该文件,并写入了一些数据,然后原先的进程执行并在此创建,由先前进程写入的数据就被擦去了。

open函数提供了原子操作,O_EXEC 和 O_CREAT ,如果文件存在就会返回出错,文件不存在则创建,使测试文件存在和创建成原子操作。

4. dup2函数

#include <unistd.h>

int dup(int filedes);

int dup2(int filedes, int filedes2);

dup2的操作先关闭filedes2文件,然后连接filedes文件对象到filedes2上。

dup2的操作等效于:

close(filedes2);

fcntl(filedes, F_DUPFD, filedes2);

dup2使close和fcntl成为一个原子操作

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值