RT-Thread论坛
直播中

rosa

13年用户 1297经验值
私信 关注
[问答]

dfs_v1,vnode引用计数只增不减,无法释放怎么解决?

我在使用RTT V5.1.0,DFSV1组件,在shell中执行cat /logs/ulog.log查看日志,每执行一次,ref引用计数就加1,如下图:

执行一次cat指令后:

cat指令的代码如下:

  • void cat(const char *filename)
  • {
  •     struct dfs_file fd;
  •     int length = 0;
  •     char buffer[81];

  •     fd_init(&fd);
  •     if (dfs_file_open(&fd, filename, O_RDONLY) < 0)
  •     {
  •         rt_kprintf("Open %s failedn", filename);

  •         return;
  •     }

  •     do
  •     {
  •         rt_memset(buffer, 0x0, sizeof(buffer));
  •         length = dfs_file_read(&fd, (void *)buffer, sizeof(buffer) - 1);
  •         if (length > 0)
  •         {
  •             buffer[length] = '�';
  •             rt_device_t out_device = rt_console_get_device();
  •             rt_device_write(out_device, 0, (void *)buffer, sizeof(buffer));
  •         }
  •     } while (length > 0);
  •     rt_kprintf("n");

  •     dfs_file_close(&fd);
  • }
  • FINSH_FUNCtiON_EXPORT(cat, print file);


使用dfs_file_open()打开文件,读取数据,之后关闭文件,open函数里会对vnode引用计数加一,close()函数中却没有对vnode引用计数减一,计数减一的代码在dfs_posix.c中的close()函数里,代码如下:

  • int close(int fd)
  • {
  •     int result;
  •     struct dfs_file *d;

  •     d = fd_get(fd);
  •     if (d == NULL)
  •     {
  •         rt_set_errno(-EBADF);

  •         return -1;
  •     }

  •     result = dfs_file_close(d);
  •     fd_release(fd);

  •     if (result < 0)
  •     {
  •         rt_set_errno(result);

  •         return -1;
  •     }

  •     return 0;
  • }
  • RTM_EXPORT(close);



回帖(1)

敷衍作笑谈

2025-9-15 17:50:00

针对 dfs_v1 中 vnode 引用计数只增不减的问题,您的 cat 命令未正确关闭文件是关键原因。以下是解决方案:


1. 修复 cat 函数:关闭打开的文件


在文件操作结束后,必须调用 dfs_file_close() 关闭文件描述符,以释放资源并减少引用计数。修改后的代码如下:


void cat(const char *filename)
{
    struct dfs_file fd;
    int length = 0;
    char buffer[81];

    fd_init(&fd);
    if (dfs_file_open(&fd, filename, O_RDONLY) < 0)
    {
        rt_kprintf("Open %s failedn", filename);
        return; // 打开失败时直接退出
    }

    // 读取文件内容并输出
    do {
        memset(buffer, 0, sizeof(buffer));
        length = dfs_file_read(&fd, buffer, sizeof(buffer) - 1);
        if (length > 0) {
            rt_kprintf("%s", buffer); // 确保正确输出内容
        }
    } while (length > 0);

    // !!! 关键修复:关闭文件 !!!
    dfs_file_close(&fd); // 释放 vnode 引用
}

2. 验证引用计数释放



  • 测试方法

    1. 执行修复后的 cat /logs/ulog.log

    2. 在 Shell 中输入 list_fd 命令(RTT 内置命令)检查文件描述符是否被释放。

    3. 或使用调试工具(如 Log 或 Debugger)观察 struct dfs_vnoderef_count 是否在每次 close 后减少。



3. 其他注意事项



  • Shell 命令实现检查:确保其他自定义文件操作(如 cpmv)在 dfs_file_open() 后均正确调用了 dfs_file_close()

  • 资源泄漏检测

    • 开启 DFS 组件的调试选项(如 RT_DEBUG_DFS_VNODE_REF),跟踪引用计数变化。

    • 监控系统内存和资源使用情况,确保长期运行无泄漏。



4. DFS v1 设计机制说明



  • 引用计数规则

    • dfs_file_open()vnode->ref_count++

    • dfs_file_close()vnode->ref_count--

    • ref_count == 0 时,文件系统才会释放 vnode 资源。


  • 未关闭的后果:每次 open 不匹配 close 会导致 ref_count 永久递增,最终耗尽资源。


5. 系统组件兼容性



  • RTT 版本支持:您使用的 5.1.0 是稳定版本,此问题非版本缺陷,而是使用未遵循“打开后关闭”原则。

  • DFS v2 优化:如果升级到 RTT 新版(如 5.1.1+),DFS v2 有更健壮的内存管理,但仍需正确调用 close


验证结果


修复后,重复执行 cat 命令时,引用计数将保持不变(每打开后关闭,计数先增后减)。示例调试输出:


# 执行 cat 前
vnode ref_count = 1  
# 执行 cat 后
vnode ref_count = 1   // 不再累积


总结问题根源是文件未关闭,而非 DFS v1 自身 Bug。通过补全 dfs_file_close() 调用即可解决。建议检查所有涉及文件操作的代码路径,确保资源释放。


举报

更多回帖

发帖
×
20
完善资料,
赚取积分