linux编程手册-课后习题之open参数O_APPEND保证函数原子性

参数flag:O_APPEND

如果打开文件以O_APPEND,则在多线程下,该函数是原子操作。
问题:打开文件操作,会发生指定文件不存在的情况,如果打开以O_CREAT方式,则会创建文件,然后再打开该文件,这是两步操作。多线程下,可能open函数创建了文件之后,时间片用光了,其它线程抢占CPU运行,这会发生不可预知的事情。
如果以追加方式打开则保证open函数原子性。

下面以有趣的课后题来分析这个参数:

《linux编程手册》课后题5-3:

本习题的设计目的在于展示为何以 O_APPEND 标志打开文件来保障操作的原子性是必要的。请编写一程序,可接收多达 3 个命令行参数:

$ atomic_append filename num-bytes [x]

该程序应打开所指定的文件(如有必要,则创建之),然后以每次调用 write()写入一个字节的方式,向文件尾部追加 num-bytes 个字节。缺省情况下,程序使用 O_APPEND标志打开文件,但若存在第三个命令行参(x),那么打开文件时将不再使用O_APPEND 标志,代之以在每次调用 write()前调用 lseek(fd,0,SEEK_END)。同时运行该程序的两个实例,不带 x 参数,将 100 万个字节写入同一文件:

$ atomic_append f1 1000000 & atomic_append f1 1000000

重复上述操作,将数据写入另一文件,但运行时加入 x 参数:

$ atomic_append f1 1000000 x & atomic_append f1 1000000 x

代码

#include <stdio.h>
#include<unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include<sys/stat.h>
#include<string.h>
#include<fcntl.h>
#include<errno.h>


int main(int argc, char const *argv[])
{
    if(argc > 4 || 0 == strcmp(argv[1],"--help"))
    {
        printf("%s test write O_APPEND\n",argv[0]);
    }
    //char* filename;
    long long num_byte;
    char buf = 'x';
    int fd ;
    if(argc == 3)
    {
        fd = open(argv[1],O_CREAT|O_WRONLY|O_APPEND,S_IRUSR|S_IWUSR);
        num_byte = atoll(argv[2]);
        while (num_byte--)
        {
            if(-1 == write(fd,&buf,1)) //write one byte once;
            {
                perror("write");
            }
        }
        if(-1 == close(fd))
        {
            perror("close file");
        }
    }
    if(argc == 4)
    {
        
        fd = open(argv[1],O_CREAT|O_WRONLY,S_IRUSR|S_IWUSR);
        num_byte = atoll(argv[2]);
        while (num_byte--)
        {
            if(lseek(fd,0,SEEK_END) == -1)
            {
                perror("lseek");
            }
            if(-1 == write(fd,&buf,1)) //write one byte once;
            {
                perror("write");
            }
        }
        if(-1 == close(fd))
        {
            perror("close file");
        }
    }

    return 0;
}



结果

生成两个文件WriteFileOne.txt和WriteFileTwo.txt,同样是写入200万个字节,但是如果不以 O_APPEND打开文件,而是用lseek函数来移动写入到末尾,则会出现写入覆盖,导致WriteFileTwo.txt小于200万个字节。这说明了O_APPEND可以保证open函数的原子性。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值