Linux应用编程之多次打开同一文件进行读写操作与 O_APPEND 标志

重复打开同一个文件,进行写操作,譬如一个进程中两次调用 open 函数打开同一个文件,分别得到两 个文件描述符 fd1 和 fd2,使用这两个文件描述符对文件进行写入操作,那么它们是分别写(各从各的位置 偏移量开始写)还是接续写(一个写完,另一个接着后面写)?因为这两个文件描述符所对应的读写位置偏移量是相互独立的,所以是分别写。



示例代码:

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

int main(void)
{
    unsigned char buffer1[4], buffer2[4];
    int fd1, fd2;
    int ret;
    int i;

    /* 创建新文件 test_file 并打开 */
    fd1 = open("./test_file", O_RDWR | O_CREAT | O_EXCL,
               S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (-1 == fd1)
    {
        perror("open error");
        exit(-1);
    }

    /* 再次打开 test_file 文件 */
    fd2 = open("./test_file", O_RDWR);
    if (-1 == fd2)
    {
        perror("open error");
        ret = -1;
        goto err1;
    }

    /* buffer 数据初始化 */
    buffer1[0] = 0x11;
    buffer1[1] = 0x22;
    buffer1[2] = 0x33;
    buffer1[3] = 0x44;

    buffer2[0] = 0xAA;
    buffer2[1] = 0xBB;
    buffer2[2] = 0xCC;
    buffer2[3] = 0xDD;

    /* 循环写入数据 */
    for (i = 0; i < 4; i++)
    {
        ret = write(fd1, buffer1, sizeof(buffer1));
        if (-1 == ret)
        {
            perror("write error");
            goto err2;
        }
        ret = write(fd2, buffer2, sizeof(buffer2));
        if (-1 == ret)
        {
            perror("write error");
            goto err2;
        }
    }

    /* 将读写位置偏移量移动到文件头 */
    ret = lseek(fd1, 0, SEEK_SET);
    if (-1 == ret)
    {
        perror("lseek error");
        goto err2;
    }

    /* 读取数据 */
    for (i = 0; i < 8; i++)
    {
        ret = read(fd1, buffer1, sizeof(buffer1));
        if (-1 == ret)
        {
            perror("read error");
            goto err2;
        }
        printf("%x%x%x%x", buffer1[0], buffer1[1],
               buffer1[2], buffer1[3]);
    }

    printf("\n");
    ret = 0;
err2:
    close(fd2);
err1:
    /* 关闭文件 */
    close(fd1);
    exit(ret);
}
示例代码中,重复两次打开 test_file 文件,分别得到两个文件描述符 fd1 fd2 ;首先通过 fd1 写入 4 个字节数据(0x11、 0x22 0x33 0x44 )到文件中,接着再通过 fd2 写入 4 个字节数据(0xaa、 0xbb 、 0xcc、 0xdd )到文件中,循环写入 4 此;最后再将写入的数据读取出来,将其打印到终端。如果它们是分别写,那么读取出来的数据就应该是 aabbccdd…… ,因为通过 fd1 写入的数据被 fd2 写入的数据给覆盖了;如果它们是接续写,那么读取出来的数据应该是 11223344aabbccdd……


编译测试:



从打印结果可知,它们确实是分别写。如果想要实现接续写,我们可以使用 O_APPEND 标志来解决这个问题。
open 函数使用 O_APPEND 标志,在使用 write 函数进行写入操作时,会自动将偏移量移动到文件末尾,也就是每次写入都是从文件末尾开始。

示例代码:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    unsigned char buffer1[4], buffer2[4];
    int fd1, fd2;
    int ret;
    int i;

    /* 创建新文件 test_file 并打开 */
    fd1 = open("./test_file", O_RDWR | O_CREAT | O_EXCL | O_APPEND,
               S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
    if (-1 == fd1)
    {
        perror("open error");
        exit(-1);
    }

    /* 再次打开 test_file 文件 */
    fd2 = open("./test_file", O_RDWR | O_APPEND);
    if (-1 == fd2)
    {
        perror("open error");
        ret = -1;
        goto err1;
    }

    /* buffer 数据初始化 */
    buffer1[0] = 0x11;
    buffer1[1] = 0x22;
    buffer1[2] = 0x33;
    buffer1[3] = 0x44;

    buffer2[0] = 0xAA;
    buffer2[1] = 0xBB;
    buffer2[2] = 0xCC;
    buffer2[3] = 0xDD;

    /* 循环写入数据 */
    for (i = 0; i < 4; i++)
    {
        ret = write(fd1, buffer1, sizeof(buffer1));
        if (-1 == ret)
        {
            perror("write error");
            goto err2;
        }
        ret = write(fd2, buffer2, sizeof(buffer2));
        if (-1 == ret)
        {
            perror("write error");
            goto err2;
        }
    }

    /* 将读写位置偏移量移动到文件头 */
    ret = lseek(fd1, 0, SEEK_SET);
    if (-1 == ret)
    {
        perror("lseek error");
        goto err2;
    }

    /* 读取数据 */
    for (i = 0; i < 8; i++)
    {
        ret = read(fd1, buffer1, sizeof(buffer1));
        if (-1 == ret)
        {
            perror("read error");
            goto err2;
        }
        printf("%x%x%x%x", buffer1[0], buffer1[1],
               buffer1[2], buffer1[3]);
    }

    printf("\n");
    ret = 0;
err2:
    close(fd2);
err1:
    /* 关闭文件 */
    close(fd1);
    exit(ret);
}

在上个示例代码基础上,我们在open函数添加了 O_APPEND 标志,其它部分不变。
 

编译测试:


从打印出来的数据可知,加入了 O_APPEND 标志后,分别写已经变成了接续写。

 


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值