2025年4月5日 星期六 乙巳(蛇)年 正月初六 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 精彩资源

一个exfat U盘引起的systen crash

时间:04-17来源:作者:点击数:23

最近遇到一个奇葩的问题,客户反馈,在Android 系统的TV上,插入exfat格式的U盘,然后就system crash了,经过一系列分析后,我们找到了原因,把分析过程分享下,希望对有类似的问题的朋友参考:

由于kernel打印的信息比较多,我们截取比较重要的信息分析:

这里out_of_memory了, 内存耗尽了,我们继续看看下面的打印,看看是哪个进程导致的内存消耗

这里我们发现了fsck.exfat进程消耗了比较大的内存, 213754*4k(page size)=834M, 我们是1G的内存

为了验证fsck.exfat在校验过程的内存消耗,我们保存从插入U盘,到system crash过程的内存消耗

从插入U盘后,我们可以看到fsck.exfat后台消耗的内存在一直增加,最后消耗到800M+后就system crash了.

由于fsck.exfat 标准的开源的文件系统校验工具,应该不存在问题,我们备份了U盘的内容,打算把U盘格式化下,再验证,就在我们备份U盘内容的时候,发现了U盘的问题,其中某个文件异常了,出现了无限循环的路径地址, Windows电脑弹出了提示信息:

就是这个文件,我们在备份的时候异常了,貌似有个无限循环的路径地址,是不是就是这个原因导致的我们的fsck出问题了呢,我们查看下fsck.exfat的源码:

  • static void dirck(struct exfat* ef, const char* path)
  • {
  • struct exfat_node* parent;
  • struct exfat_node* node;
  • struct exfat_iterator it;
  • int rc;
  • size_t path_length;
  • char* entry_path;
  • if (exfat_lookup(ef, &parent, path) != 0)
  • exfat_bug("directory `%s' is not found", path);
  • if (!(parent->flags & EXFAT_ATTRIB_DIR))
  • exfat_bug("`%s' is not a directory (0x%x)", path, parent->flags);
  • path_length = strlen(path);
  • entry_path = malloc(path_length + 1 + EXFAT_NAME_MAX);
  • if (entry_path == NULL)
  • {
  • exfat_error("out of memory");
  • return;
  • }
  • strcpy(entry_path, path);
  • strcat(entry_path, "/");
  • rc = exfat_opendir(ef, parent, &it);
  • if (rc != 0)
  • {
  • free(entry_path);
  • exfat_put_node(ef, parent);
  • exfat_error("failed to open directory `%s'", path);
  • return;
  • }
  • while ((node = exfat_readdir(ef, &it)))
  • {
  • exfat_get_name(node, entry_path + path_length + 1, EXFAT_NAME_MAX);
  • exfat_debug("%s: %s, %"PRIu64" bytes, cluster %u", entry_path,
  • IS_CONTIGUOUS(*node) ? "contiguous" : "fragmented",
  • node->size, node->start_cluster);
  • if (node->flags & EXFAT_ATTRIB_DIR)
  • {
  • directories_count++;
  • dirck(ef, entry_path);
  • }
  • else
  • files_count++;
  • nodeck(ef, node);
  • exfat_put_node(ef, node);
  • }
  • exfat_closedir(ef, &it);
  • exfat_put_node(ef, parent);
  • free(entry_path);
  • }
  • static void fsck(struct exfat* ef)
  • {
  • exfat_print_info(ef->sb, exfat_count_free_clusters(ef));
  • dirck(ef, "");
  • }

显然,在fsck的时候,会调用dirck函数, 这个函数会递归运行,遇到这种无限循环的目录,肯定就出不来了,每次进入dirck函数都会malloc分配内存,这样就会导致内存耗尽,好像是这么回事。

我们把U盘格式化后,在插入板上,问题消失了,系统能够正常挂载exfat的U盘了,到此,问题找到了。这个是由于U盘文件系统管理出问题,导致的无限循环的目录,引发了fsck.exfat内存耗尽。

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门