【问题标题】:glibc function fails on large fileglibc 函数在大文件上失败
【发布时间】:2022-01-25 12:57:17
【问题描述】:

我有一个多年前用 C++ 编写的实用程序,它获取给定目录的所有子目录中的所有文件,并根据文件数将它们移动到新编号的子目录中。它已经工作了好几年,没有出错。

昨天第一次失败了。它总是在 2.7Gig 视频文件上失败,这可能是这个实用程序遇到的最大的。文件本身没有损坏。它将在视频播放器中播放。我可以毫无问题地使用命令行或文件管理器应用程序移动它。

我使用 ntfw() 遍历目录子树。在这个文件上, ntfw() 在调用我的回调函数之前遇到文件时返回错误代码 -1。由于(我认为)代码只处理文件名,而不是实际打开或读取文件,我不明白为什么文件大小应该是一个问题。

打开文件描述符的数量不是问题。也不是文件的数量。它位于超过 5,000 个文件的子树中,但是当将其移动到仅有的 50 个文件之一时,它仍然失败,而原始子树的处理没有错误。文件权限不是问题。该文件与所有其他文件相同。这包括 ACL 权限。

问题是:文件大小是问题吗?为什么?

文件系统是ext4。

ldd --version /usr/lib/i386-linux-gnu/libc.so
ldd (Ubuntu GLIBC 2.27-3ubuntu1.4) 2.27
Linux version 4.15.0-161-generic (buildd@lgw01-amd64-050)
(gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04))
#169-Ubuntu SMP Fri Oct 15 13:39:59 UTC 2021

【问题讨论】:

  • /usr/lib/i386-linux-gnu?这在我看来是 32 位的。您的可执行文件是否被编译为 32 位?
  • 如果nftw() 返回-1,它应该将errno 设置为失败的原因,这将有助于将其包含在问题中(提示:perror()strerror()得到人类可读的信息,而不是一个神秘的数字)
  • @n.1.8e9-where's-my-sharem。 - 为什么 32 位会有问题?如果程序使用mmap,仍然虚拟地址空间为4G,文件大小为2.7G。如果程序不使用 mmap 会有什么问题?
  • 一些整数数据是有符号的。 32 位系统上的文件大小通常最多为 2GB 而不是 4。您应该迁移到 64 平台或使用 nftw64。

标签: linux file-handling glibc large-files


【解决方案1】:

当您使用 32 位应用程序时,为了能够正常处理大于 2 GB 的文件,您应该使用 -D_FILE_OFFSET_BITS=64 进行编译,以便使用 64 位文件处理系统调用和类型。

特别是,如果文件大小超过 2 GB,nftw() 调用 stat() 会失败并显示 EOVERFLOW:https://man7.org/linux/man-pages/man2/stat.2.html

此外,对于使用 mmap() (您似乎没有使用,但以防万一评论提到它),您不能分配全部 4 GB,一些地址空间保留用于内核(在 Linux 上通常为 1 GB)。然后堆栈、共享库等会使用一些空间。如果幸运的话,也许您一次可以映射 2 GB。

【讨论】:

  • 编译标志立即解决了问题。我忘记了 2GB 的限制。谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-11-15
  • 2012-05-31
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
相关资源
最近更新 更多