首页 > 其他分享 >RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录

时间:2023-10-25 18:05:30浏览次数:39  
标签:RT 文件大小 len so printf fopen Smart size


前言

  • RT-Smart 应用(apps)开发环境,ubuntu 20.04 + win10 VS Code
  • 最近在调试一个问题,需要使用 FILE 的 fopen、fread 等去读取处理一个大文件,为了尽快复现验证问题,随手搜了一下 fopen 等几个 API的用法,调试时闹出来一个【笑话】,程序运行所到之处,把处理过的本地文件清空了。
  • 当时初步的目标只是使用 stat 去获取一个文件的大小,现象就是 0

获取文件大小

  • 如何在 用户态获取文件大小,RT-Smart 的应用开发与 Linux 的用户应用开发基本类似,Linux 平台上的应用,可以轻松的移植到 RT-Smart 上。
  • fopen 可以在RT-Smart内核态使用,也可以在用户态使用,用户态的使用,一般都是借助 libc 与 系统调用,当前 RT-Smart 使用 musl gcc 工具链
  • 获取文件大小,应该与 fopen、fread 系列无关,代码如下:
unsigned long get_file_size(const char *path)
{
    unsigned long filesize = -1;
    struct stat statbuff;

    if (stat(path, &statbuff) < 0)
    {
        return filesize;
    }
    else
    {
        filesize = statbuff.st_size;
    }

    return filesize;
}
  • 这里使用标准的 POSIX 接口 stat,头文件 #include <sys/stat.h>

测试代码

  • 随手摘抄修改了一个测试代码,想获取到 文件大小,然后分批读取,验证这个过程是否正常,哪想到文件大小获取为0,使用 qemu 调试了多遍,怀疑文件系统BUG,依旧未找到正确的思路
  • 原 BUG 测试代码如下:
/*  read big file : > 300MB */

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

#define BUFFER_SIZE     (8 * 1024 * 1024)

unsigned long get_file_size(const char *path)
{
    unsigned long filesize = -1;
    struct stat statbuff;

    if (lstat(path, &statbuff) < 0)
    {
        return filesize;
    }
    else
    {
        filesize = statbuff.st_size;
    }

    return filesize;
}

int main(int argc, char **argv)
{
    //int errno;
    FILE *fp = NULL;
    unsigned long so_far, signed_len;
    const char *path = "/lib/libc.so";
    char *buffer = NULL;
    size_t size;
    size_t file_size;
    size_t rd_len;

    if (argc > 1)
    {
        path = argv[1];
    }

    printf("filename path : %s\n", path);

    fp = fopen(path, "w+");
    if (!fp)
    {
        printf("fopen failed\n");
        return -1;
    }

    buffer = malloc(BUFFER_SIZE);
    if (!buffer)
    {
        printf("buffer alloc failed\n");
        return -1;
    }

    file_size = get_file_size(path);
    printf("file size %ld\n", file_size);

    signed_len = file_size;
    so_far = 0;

    while (so_far < signed_len)
    {
        size = BUFFER_SIZE;
        printf("so far is %lu, signed_len is %lu, size is %lu\n", so_far, signed_len, size);

        if (signed_len - so_far < size)
            size = signed_len - so_far;

        printf("new size is %lu\n", size);

        rd_len = fread(buffer, 1, size, fp);
        printf("fread rd_len = %ld\n", rd_len);
        if ((rd_len != 0) && (rd_len != size))
        {
            printf("fread failed, rd_len = %ld, size = %ld\n", rd_len, size);
            fclose(fp);
            free(buffer);
            return -2;
        }
        so_far += size;
        printf("fread so_far = %ld\n", so_far);
    }

    fclose(fp);
    free(buffer);
    printf("fread big file test end!\n");

    return 0;
}
  • 测试结果
  • 文件大小 读取 为 0

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_用户态

  • 由于可以使用 qemu 来调试,我看看到底为何 大小为0,难道 打印的不对?

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_清空文件_02

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_fopen_03

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_清空文件_04

  • 内核部分的 sys_stat 后面的调试就不放上来了,说明一个问题:文件获取大小就是 0

回头看下测试结果

  • 好吧,我发现了文件系统BUG?读取一下状态,文件大小就变为 0 了?
  • 我多试读取了几个文件,文件大小真的变为了0,包括 /lib/libc.so 这个默认文件
  • 我在板子上试了一下,读取了一下文件系统中的核心文件: rtthread.bin,哪想到,板子启动不了,看了固件被【真正】清零0

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_#include_05

赶快看看神奇的代码

  • 发现 BUG 了,原来在 获取文件状态前,有个 fopen 操作,并且使用了 "w+",就是这个问题

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_清空文件_06

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_#include_07

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_文件大小_08

  • 都是C 语言基础薄弱惹的祸,记录一下,以后得好好学习,正确理解,才能致用。

fopen 的 参数

  • 当前发现 fopen 使用 “a+” 也不能获取文件大小,二进制的文件,需要使用 “rb”

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_清空文件_09

  • 正常使用了 fopen 后,文件大小就正常获取了

RT-Smart 应用开发笔记:fopen 造成文件被清空问题的分析记录_文件大小_10

  • 看来测试代码,也需要认真写,测试过程中【看似无关紧要】的代码,也许就是个【地雷】

小结

  • 以上记录,其实就是 fopen 参数的使用方法的一个记录,写这么多,就是增加【印象】,得到【教训】,防止编写此类BUG 的事情不再重复犯
  • 获取知识途径很多,有时候有些 BUG的出现,会针对性的让你获取更多,嵌入式开发,除了博闻强记,更重要的,就是有个【烂笔头】记录点点滴滴。


标签:RT,文件大小,len,so,printf,fopen,Smart,size
From: https://blog.51cto.com/zhangsz0516/8023590

相关文章

  • Python编程快速上手(第2版)2021年pdf电子版 Al Sweigart
    Python编程快速上手(第2版)2021年pdf电子版AlSweigart作者: [美]AlSweigart原作名: AutomatetheBoringStuffwithPython:PracticalProgrammingforTotalBeginners出版年: 2021-3-1ISBN: 9787115551870连接提取码:a0si本书用示例程序,介绍了一些实际的编程案例。建议自......
  • linux vmware导出windows11到virtual box
    如果直接使用virtualbox导入会报错Hostresourceoftype"OtherStorageDevice(20)"issupportedwithSATAAHCIorvirtio-scsicontrollersonly,line48(subtype:vmware.nvme.controller).找到导出目录下的ovf文件,上面说的是48行,那么找到48行<Item>......
  • VirtualBox上安装CentOS7
    下载CentOS7ISO镜像文件:前往CentOS官方网站的镜像下载页面:Download在页面上找到适合你系统架构的CentOS7ISO镜像文件,并下载到本地。安装VirtualBox:前往VirtualBox官方网站的下载页面:Downloads–OracleVMVirtualBox根据你的操作系统,选择合适的......
  • 软件测试|Python数据可视化神器——pyecharts教程(十)
    使用pyecharts绘制漏斗图简介漏斗图(FunnelChart)是一种用于可视化数据流程或转化率的图表类型。它通常由一系列阶段组成,每个阶段都有一个名称和一个值,表示在该阶段的转化量或数据流程的进展情况。漏斗图的名称来源于其外观,类似于实际的漏斗形状,它的顶部较宽,底部较窄,符合数据逐渐减......
  • RTSP视频流媒体服务器LiteCVR v3.1更新:通道收藏优化
    在安防视频监控行业,监控摄像头也正从"看得见"到"看得清"开始转变,现在的网络智能摄像头,不仅可以拥有高清超高清的监控画质,还能对记录的视频中的人或物体进行识别。近期我们对LiteCVR增加了普通用户的收藏功能,今天来简单介绍一下。在LiteCVRv3.1版本之前,普通用户只能查看分配给自己......
  • RTSP视频监控平台LiteCVR v3.1更新:通道收藏优化
    在安防视频监控行业,监控摄像头也正从"看得见"到"看得清"开始转变,现在的网络智能摄像头,不仅可以拥有高清超高清的监控画质,还能对记录的视频中的人或物体进行识别。近期我们对LiteCVR增加了普通用户的收藏功能,今天来简单介绍一下。在LiteCVRv3.1版本之前,普通用户只能查看分配给......
  • pyecharts配置项说明
    pyecharts配置项说明一、全局配置项在pyecharts中,一切皆配置!pyecharts全局配置项:全局配置项-pyecharts-APythonEchartsPlottingLibrarybuiltwithlove.全局配置项可通过set_global_opts方法设置InitOpts:初始化配置初始化配置是在实例化图形类初始化的:c=Bar(......
  • RTMP流媒体服务器LiteCVR支持在iOS播放WebRTC低延时视频流
    视频监控设备是安防行业的细分专业领域,近年来,视频监控业务正在向其他领域加速渗透。众所周知,iOS系统支持HLS流,但是HLS流延时高,无法满足实时流的要求;而WebRTC播放延时低,因此,很多用户希望能在iOS系统上播放Webrtc视频流。针对用户的这一需求,LiteCVR平台灵活的视频能力,可以完全满足。......
  • RecureCRT连接VMware虚拟机Centos7及网络配置
    1.确认物理机ip地址2.打开VMware,点击网络适配器并且选择NET模式3.打开WMware,点击左上角编辑,虚拟网络编辑器,设置子网ip和子网掩码 4.设置好之后点击上图中的NET设置,查看网关IP5.打开并进入虚拟机,配置网络信息,输入如下命令:vim/etc/sysconfig/network-scripts/ifconfig-e**......
  • 云图说|华为云CodeArts Build,云端化的编译构建平台
    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说)、深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云。更多精彩内容请单击此处。本文分享自华为云社区《云图说|华为云CodeArtsBuild,云端化的编译构建平台》,作者:阅识风云。互联网企......