fwrite+flock异常情况测试

问题:

  • 多进程/线程写同一文件时,此时需要加锁,但如果还涉及更名、删除此文件的操作,会不会有异常出现呢?程序会不会因此挂掉呢?

测试:(下面按照几种不同情况进行测试)

  1.  更名操作 ==》两个进程都打开文件之后,一个锁住(IOTest),一个等待锁(IOTest2),此时修改文件iotest.log的名字
    修改文件名之前的状态
    修改文件名之后状态(两个进程都可以成功写入)

  2.  更名操作 ==》IOTest进程打开文件并锁住文件,IOTest2不打开文件,此时修改文件iotest.log的名字
    修改文件名之前的状态
    修改文件名之后状态(IOTest进程数据写入至修改文件名后的文件,IOTest2进程数据写入新创建iotest.log文件)

  3. 删除操作 ==》两个进程都打开文件,一个进程锁住(IOTest),一个进程等待锁(IOTest2),此时删除文件
    删除文件后,进程分别处于锁和等待锁状态
    删除文件后继续操作,未发生报错,程序正常锁、解锁、关闭描述符等

  4. 删除操作 ==》单独起一个进程,strace跟踪情况
    正常运行


结论:

  1. 只要是文件被进程打开了,那之后无论是文件更名,还是进程加锁、解锁,进程最终指向的都是此文件,内容也一定是写入此文件,并写入成功的
  2. 如果文件被进程打开之后,后来又被删除掉了,那无论进程加锁、解锁、还是写数据,都不会报错,当然虽然不报错,但写入的数据写到哪里就不得而知了

测试代码:

/****** IOTest ******/

#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/file.h>
#include <stdio.h>
#include <sys/time.h>

#define IOTEST_DIR      "/tmp/"
#define IOTEST_WSTR     "this is iotest\n"

static void iotest_print(char *pstr)
{
    char c[8];

    printf("%s\n", pstr);
    fgets(c, 8, stdin);

    return;
}

int main()
{
    int         r;
    FILE        *fp = NULL;
    char        fpath[256] = {0};
    char        *pstr;

    snprintf(fpath, sizeof(fpath), "%siotest.log", IOTEST_DIR);
    
    iotest_print("即将打开/创建文件, 继续请按任意键...");
    
    fp = fopen(fpath, "at+");
    if (fp == NULL)
    {
        printf("fopen failed: %s\n", strerror(errno));
        return -1;
    }

re_lock:
    iotest_print("即将锁住此文件, 继续请按任意键...");
    
    r = flock(fileno(fp), LOCK_EX);
    if (r)
    {
        if (errno == EINTR)
        {
            goto re_lock;
        }

        fclose(fp);
        fp = NULL;
        return -1;
    }

    iotest_print("即将写入数据至缓冲区, 继续请按任意键...");
    fwrite(IOTEST_WSTR, sizeof(IOTEST_WSTR), 1, fp);

    iotest_print("即将把数据从缓冲区刷入磁盘, 继续请按任意键...");
    fflush(fp);

re_input:
    iotest_print("即将解锁, 继续请按任意键...");

    flock(fileno(fp), LOCK_UN);

    iotest_print("解锁完成, 即将关闭描述符, 继续请按任意键...");
    fclose(fp);

    printf("文件描述符已关闭, 操作完成, 正在退出...\n");
    return 0;
}
/****** IOTest2 ******/

#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/file.h>
#include <stdio.h>
#include <sys/time.h>

#define IOTEST2_DIR      "/tmp/"
#define IOTEST2_WSTR     "this is iotest2\n"

static void iotest2_print(char *pstr)
{
    char c[8];

    printf("%s\n", pstr);
    fgets(c, 8, stdin);

    return;
}

int main()
{
    int         r;
    FILE        *fp = NULL;
    char        fpath[256] = {0};
    char        *pstr;

    snprintf(fpath, sizeof(fpath), "%siotest.log", IOTEST2_DIR);
    
    iotest2_print("即将打开/创建文件, 继续请按任意键...");
    
    fp = fopen(fpath, "at+");
    if (fp == NULL)
    {
        printf("fopen failed: %s\n", strerror(errno));
        return -1;
    }

re_lock:
    iotest2_print("即将锁住此文件, 继续请按任意键...");
    
    r = flock(fileno(fp), LOCK_EX);
    if (r)
    {
        if (errno == EINTR)
        {
            goto re_lock;
        }

        fclose(fp);
        fp = NULL;
        return -1;
    }

    iotest2_print("即将写入数据至缓冲区, 继续请按任意键...");
    fwrite(IOTEST2_WSTR, sizeof(IOTEST2_WSTR), 1, fp);

    iotest2_print("即将把数据从缓冲区刷入磁盘, 继续请按任意键...");
    fflush(fp);

re_input:
    iotest2_print("即将解锁, 继续请按任意键...");

    flock(fileno(fp), LOCK_UN);

    iotest2_print("解锁完成, 即将关闭描述符, 继续请按任意键...");
    fclose(fp);

    printf("文件描述符已关闭, 操作完成, 正在退出...\n");
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值