发布作品
    楼主
    WZCPC头像WZCPC头像

    WZCPC

    拿铁DHT-PHEV车主·车龄1年

    • 车评创作力LV1车评创作力LV1
    • 登录大师LV2登录大师LV2
    • 懂车评论员LV2懂车评论员LV2
    • 持之以恒LV2持之以恒LV2
    • 懂车智多星LV3懂车智多星LV3
    • 内容鉴赏官LV5内容鉴赏官LV5

    这咖啡不够香——魏牌拿铁记录仪丢数据分析 -转自一位车友

    2023-02-28发布于:拿铁DHT-PHEV车友圈

    #汽车问题反馈

    这咖啡不够香

    ——魏牌拿铁记录仪丢数据分析       

    2023年1月底买了这车,大概一个月不到后,我就发现了记录仪丢数据,满心期待的等了一年,一次进站升级,两次OTA升级后,发现问题依旧。因为工作需要,对FAT32文件系统还算熟悉,因此试图分析一下出现问题的原因到底在哪儿。

    分析前使用车机自带的格式化功能,将外部和内部两张卡全部格式化后进行测试,录像一分钟后熄火断电取卡,分析这一分钟内的三个视频(外部卡上的前视, 环视和内部卡上的车内)。使用的分析工具是老旧的WinHex,在管理员权限打开时能直接分析物理磁盘。

    1. 对内部卡进行分析。我使用的是原厂的8G卡。下面是其基本信息

     

     

    可以看出,一个扇区大小是512字节,一个簇的大小是4096,也就是4K。数据区起始是29974,没有4K对齐。这个卡容量小,可能硬件扇区大小不是4K,没有影响。

    然后分析文件的簇列表。因为只需要录制一个视频,所以整个文件是连续存储的,没有任何碎片。

     

    2. 对外部卡进行分析

     

    扇区大小与簇大小与8G卡一致,第一数据扇区可以被8整除,也就是数据区4K对齐了。

    将同时生成的两个文件的簇列表拉出来看(前视在左,环视在右)。

     

    由于卡是刚格式化过的,没有其它文件干扰。发现每个文件的第一个簇就是碎片,后面的两个文件是轮流保存的。基本思路是每个文件大概存260个簇左右(注意这个大小不是256,也就是1M字节),就换另一个文件。

     

    如果是一次写1M字节,由于我们的卡一般连续写入速度都是至少都是20M以上的,对付这种一秒钟只需要保存2M的数据的情况还是很轻松的。如果正常这样操作下去,不应该会出现丢数据的情况。

    不出意外,下面就要出意外了。大概在每边写了6M之后,开始出现数据没有连续写入的情况。

     

    甚至出现了每边4K写着玩的情况:

     

    后面更是出现大量的每边写4K的情况:

     

    然后突然又正常了,还是每边写1M字节左右,每边大概写了25M左右,突然又崩溃,开始随机写入。大概写一个文件,会崩溃三次。

    分析出现无法连续写入的起始簇号,基本上都符合 “簇号*4/4096接近整数”这个规律。下面是我这次测试的结果:

    解释一下”簇号*4/4096”的意义。FAT32中,一个簇占用4个字节,再除以4096是看需要更新的FAT表占用了多少个物理扇区。

    当数据在不停写入时,FAT表同时也需要更新,最开始时,这个更新是在内存中执行的,但是一旦FAT表需要更新的数据达到一定量后,文件系统底层需要将FAT表写入到TF卡。文件系统底层应该会挑选物理扇区的整数倍进行更新。出错的簇号都在物理扇区的整数倍附近,说明极有可能出错的原因是由于底层更新FAT表,导致底层文件系统繁忙导致的。

    由于连续出现4K碎片,需要分析这4K碎片是如何产生的。开始我认为是由于两个线程同时写文件,文件系统底层会将两边的写操作拆解开,一个文件写一点,后来感觉这个思路不对,文件系统底层不可能这么蠢。于是我在Windows下创建了一个简单的双线程程序,同时对TF卡进行写操作,测试结果是,如果一个线程在写文件的话,另一个线程的写操作是强制进入等待状态的,我猜测在Linux下应该是类似的。所以在TF卡刚格式化时,文件中出现的最小的碎片,就是程序写文件时最小的缓冲区大小。经过多次测试后,我设置为程序每次写入4K,结果就得到了与车机上类似的簇列表。同样也是第一个簇就是碎片,后面两边开始轮流。不过由于文件系统的不同,能连续写入的簇数量不一致。

     

    测试代码如下(VS2019 C++): 

    #include <iostream>

    #include <thread>

    #include <Windows.h>

     

    using namespace std;

     

    char testbuf[1024 * 1024];

     

    void test(FILE* fp)

    {

        for (int i = 0; i < 256*60; i++)

        {

            fwrite(testbuf, 4096, 1, fp);

        }

        return;

    }

     

    int main()

    {

        FILE* fp1 = NULL;

        FILE* fp2 = NULL;

     

        cout << "主线程开始" << endl;

     

        if (fopen_s(&fp1, "J:\\a.bin", "wb") != 0)

        {

            cout << "Create file a.bin fail." << endl;

            return 1;

        }

        if(fopen_s(&fp2, "J:\\b.bin", "wb") != 0)

        {

            fclose(fp1);

            cout << "Create file b.bin fail." << endl;

            return 2;

        }

     

        thread t1(test, fp1);

        thread t2(test, fp2);

        t1.join();

        t2.join();

        fclose(fp1);

        fclose(fp2);

        cout << "主线程结束!" << endl;

        return 0;

    }

    基本上就实锤了,拿铁车机在写TF卡时居然会一次只写4K,虽然不能确认是全部如此,但至少这种情况大量存在的。我们买的什么记录仪专用卡,速度标多少M每秒,都是指连续写入,可是禁不起一次写4K这种玩法的。至于怎么改,一次写1M字节就可以了。

    以上是转自一位技术行车友的问题反馈报告!

    主要是他没发到懂车帝。我就帮忙发出来让大家知道下这个问题。

    作者提到的车系:


    回复楼主


    前往