原子操作

本文探讨了在多进程环境中因文件偏移量导致的数据覆盖问题,并介绍了如何使用pread和pwrite函数实现原子操作,避免数据冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.原子操作的原因

以前的UNIX系统不支持O_APPEND选线,所以程序需要如下编辑
if(seek(fd,0L,2)<0)
 printf("seek error\n");
if(write(fd,buf,100)!=100)
 printf("write error");
但是该程序在多进程(线程)里面会有问题。
假设两个独立的进程A,B,都有打开同一个文件,但是都没有O_APPEND选项。每一个进程有自己的文件表,但是它们共享同一个v-node表。假设A进行了lseek操作,将A的文件偏移量移动到文件末尾(1500 byte处)。然后内核切换了进程,B继续运行。进程B
也进行lseek操作,也将B的文件偏移量移动到文件末尾(1500byte处),然后B进行写操作,将B的文件偏移量移动到1600byte处。
因为文件的大小被扩大了,内核也将当前文件大小扩大到1600bytes。然后内核切换到A继续执行,然后A函数调用write函数,然后
是从文件的1500byte开始写入,这样就覆盖了之前所写的内容。
    
      任何需要多于一个函数调用的操作都不能够是原子的,因为内核可能随时在两个函数之间吊起该进程。

2.pread和pwrite函数

Unix有两个函数需有应用将seek和I/O操作进行原子化。pread和pwrite
1.函数原型
#include<unistd.h>
ssize_t pread(int fd, void* bud, size_t nbytes, off_t offset);
返回值:成功读到的字节数,如果在文件末尾返回0,失败返回-1.
ssize_t pwrite(int fd, const void* bud, size_t nbytes, off_t offset);
返回值:成功写入的字节数,失败返回-1.
2.简介
调用pread函数等同于调用lseek接着调用read。但是有如下要求:
   (1.两个操作之间没有任何打断的可能。
   (2.当前文件偏移量没有更新。
调用pwrite等同于调用lseek接着调用read。但是和上面两个要求相同。

3.
通常,原子操作表示一个操作由很多步骤组成。如果一个操作时原子操作,只有两个可能:所有的步骤的执行成功或者所以的步骤
都没有执行。绝对不可能是每个步骤分步执行的。
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值