【问题标题】:How do I create a sparse file programmatically, in C, on Mac OS X?如何在 Mac OS X 上以编程方式在 C 中创建稀疏文件?
【发布时间】:2010-09-16 05:03:21
【问题描述】:

我想创建一个稀疏文件,这样在我向它们写入数据之前,全零块不会占用实际磁盘空间。有可能吗?

【问题讨论】:

  • 我认为了解您为什么需要稀疏文件会很有帮助。
  • 你的意思是稀疏磁盘映像吗?

标签: c macos filesystems


【解决方案1】:

对于默认的 Mac OS X 文件系统 (HFS+) 是否支持文件中的漏洞,似乎有些混淆。下面的程序证明情况并非如此。

#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>

void create_file_with_hole(void)
{
    int fd = open("file.hole", O_WRONLY|O_TRUNC|O_CREAT, 0600);
    write(fd, "Hello", 5);
    lseek(fd, 99988, SEEK_CUR); // Make a hole
    write(fd, "Goodbye", 7);
    close(fd);
}

void create_file_without_hole(void)
{
    int fd = open("file.nohole", O_WRONLY|O_TRUNC|O_CREAT, 0600);
    write(fd, "Hello", 5);
    char buf[99988];
    memset(buf, 'a', 99988);
    write(fd, buf, 99988); // Write lots of bytes
    write(fd, "Goodbye", 7);
    close(fd);
}

int main()
{
    create_file_with_hole();
    create_file_without_hole();
    return 0;
}

程序创建两个文件,每个文件长度为 100,000 字节,其中一个有一个 99,988 字节的孔。

在 HFS+ 分区上的 Mac OS X 10.5 上,两个文件占用相同数量的磁盘块 (200):

$ ls -ls
total 400
200 -rw-------  1 user  staff  100000 Oct 10 13:48 file.hole
200 -rw-------  1 user  staff  100000 Oct 10 13:48 file.nohole

而在 CentOS 5 上,没有漏洞的文件比其他文件多消耗 88 个磁盘块:

$ ls -ls
total 136
 24 -rw-------  1 user   nobody 100000 Oct 10 13:46 file.hole
112 -rw-------  1 user   nobody 100000 Oct 10 13:46 file.nohole

【讨论】:

    【解决方案2】:

    与其他 Unix 一样,它是文件系统的一个特性。文件系统要么支持所有文件,要么不支持。与 Win32 不同,您不需要做任何特别的事情来实现它。与 Win32 不同的是,使用稀疏文件不会降低性能。

    在 MacOS 上,默认文件系统是 HFS+,它支持稀疏文件。

    更新: MacOS 曾经支持 UFS 卷,支持稀疏文件,但已被删除。当前支持的文件系统都没有稀疏文件支持。

    【讨论】:

    • 嗯...从某种意义上说,数据分叉是 unixy 的,资源分叉是专门的怪人,不是吗?不管怎样,这并不重要。干杯。
    • 是的,“资源分叉”是古老的。大多数程序只处理“数据分叉”。
    • UFS 在 OSX Lion 中被删除。
    • 更新:macOS 现在默认为 APFS,它确实支持它。 :)
    • 如果您想了解任意卷,请使用getattrlist 获取该卷的ATTR_VOL_CAPABILITIES 属性组,然后检查VOL_CAP_FMT_SPARSE_FILES 功能。如前所述,HFS+具有此功能,但 APFS 具有。
    【解决方案3】:

    此线程成为有关稀疏文件的综合信息来源。这是 Win32 缺少的部分:

    Decent article with examples

    Tool that estimates if it makes sense to make file as sparse

    问候

    【讨论】:

      【解决方案4】:

      hdiutil 可以处理稀疏的图像和文件,但不幸的是它链接的框架是私有的。

      您可以尝试定义由下面的 DiskImages 框架定义的外部符号,但这对于生产代码来说很可能是不可接受的,而且由于该框架是私有的,您必须对其用例进行逆向工程。

      cristi:~ diciu$ otool -L /usr/bin/hdiutil

      /usr/bin/hdiutil: /System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages(兼容版本1.0.8,当前版本194.0.0) [..]

      cristi:~ diciu$ nm /System/Library/PrivateFrameworks/DiskImages.framework/Versions/A/DiskImages | awk -F' ''{打印 $3}' | c++过滤器| grep -i 稀疏

      [..]

      CSparseFile::sector2Band(long long)

      CSparseFile::addIndexNode()

      CSparseFile::readIndexNode(long long, SparseFileIndexNode*)

      CSparseFile::readHeaderNode(CBackingStore*, SparseFileHeaderNode*, unsigned long)

      [...为简洁起见]

      后期编辑

      可以使用 hdiutil 作为外部进程并让它为您创建一个稀疏磁盘映像。然后,您将在 C 进程中在(挂载的)稀疏磁盘映像中创建一个文件。

      【讨论】:

      • 您好,我只需要深入了解hdiutil 私有框架,以便以编程方式附加 DMG 文件(表示自 HFS+ 分区以来的磁盘映像的文件)。我想知道您是否碰巧在 DiskImages 框架内挖掘了一点并寻找正确的方法?谢谢
      【解决方案5】:

      如果您寻找 (fseek, ftruncate, ...) 到末尾,文件大小将增加而不分配块,直到您写入孔。但是没有办法创建一个自动将零块转换为孔的魔术文件。你必须自己做。

      这可能有助于查看(OpenBSD cp 命令插入孔而不是写入零)。 patch

      【讨论】:

      • 这在 Linux 上是正确的,但不是在默认的 Mac OS X 文件系统 HFS+ 上。请参阅我对这个问题的回答。
      • > 如果你寻找 (fseek, ftruncate, ...) 到最后,文件大小将在不分配块的情况下增加 这在 OSX 上似乎不是这样
      【解决方案6】:

      如果你想要可移植性,最后的办法是编写你自己的访问函数,这样你就可以管理一个索引和一组块。

      本质上,您管理单个文件,因为操作系统管理磁盘,保存文件中的块链、已分配/空闲块的位图等。

      当然,这会导致非优化和较慢的访问,只有在节省空间的要求绝对关键并且您有足够的时间编写一组强大的访问函数时,我才会推荐这种方法。

      即使在这种情况下,我也会首先调查您的问题是否需要其他解决方案。也许您应该以不同的方式存储数据?

      【讨论】:

        【解决方案7】:

        看起来 OS X 支持 UDF 卷上的稀疏文件。我在 OS X 10.9 上尝试了 Titandecoy 的测试程序,它确实在 UDF 磁盘映像上生成了一个稀疏文件。此外,并不是说 OS X 不再支持 UFS,所以如果您需要稀疏文件,UDF 是唯一支持它们的本机支持的文件系统。

        我还在 SMB 共享上尝试了该程序。当服务器是 Ubuntu(ext4 文件系统)时,程序会创建一个稀疏文件,但通过 SMB 的“ls -ls”不会显示该文件。如果您在 Ubuntu 主机本身上执行“ls -ls”,它确实显示文件是稀疏的。当服务器是 Windows XP(NTFS 文件系统)时,程序不会生成稀疏文件。

        【讨论】:

          猜你喜欢
          • 2015-03-22
          • 2015-05-02
          • 2011-03-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-30
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多