磁盘指针如何工作?

时间:2010-01-10 17:56:04

标签: c language-agnostic pointers swizzling

假设我想将复杂的数据结构(例如树)存储到磁盘。连接我的数据结构中的节点的内部指针是指针,但我不能只是将这些指针写入磁盘,因为当我读回数据结构时,内存位置将会发生变化。

那么将指针存储在磁盘上的正确方法是什么?答案就像(文件,偏移)一样简单,还是有些东西我不知道?我可以直觉指出如何将指针转换为(文件,偏移)对,然后再转回,但是我应该注意哪些细微之处?

编辑:我应该提一下,我特别感兴趣的是数据库如何在内部对b树进行此操作。我可能提出了比我应该更普遍的问题,尽管我很欣赏基于XML的答案。

5 个答案:

答案 0 :(得分:4)

关于(文件,偏移)对的插入是正确的。

在磁盘上存储数据时需要注意的一点是,磁盘速度很慢。因此,有一些特殊的数据结构可用于在磁盘上存储“可搜索的”数据。使用(文件,偏移)指针访问存储在磁盘上的二叉搜索树的节点比在内存中访问它们要慢几个数量级。

如果访问速度很重要,那么您希望将预期一起访问的内容存储在磁盘上。用于此的几个数据结构是B-treeB+ tree。看看这些,找出如何使用它们。数据库等多个应用程序使用了复杂的caching algorithms来缓存内存中的内容,因此应用程序无需一次又一次地访问磁盘来检索内容。

如果访问速度不重要,那么按照Aiden和Darren的建议,以XML的形式简单地“序列化”磁盘上的数据就足够了。

编辑:如果您需要有关数据库如何在磁盘上存储数据的更多详细信息,您需要了解有关数据库理论的更多信息。我建议在数据库中读取good book,以便了解驱动磁盘格式的要求。请注意,我在这里主要指的是relational databases,但other breeds databasesdifferent requirements完全Database recovery因此不同磁盘格式。从关系数据库开始是一件好事,因为它们是最常用的。

简而言之,影响关系数据库磁盘格式的一些事情是:

  1. 磁盘读/写性能
  2. Relations between entities(如果有腐败)
  3. Transactional support
  4. 垃圾收集
  5. Primary index
  6. Query optimization
  7. started是数据库理论的一个重要分支,用于优化磁盘访问,以满足查询。希望这会在right direction中为您{{3}}。

答案 1 :(得分:1)

无论如何你喜欢。您可以将其存储为每个节点的文件系统顶部的其他文件的引用,或者编写使用块引用的文件系统驱动程序。

提供了:

  1. 您的节点包含对持久存在的位置的引用
  2. 您可以在编写节点时知道要写入的位置
  3. 你可以按照自己的意愿去做。使用基于磁盘的inode系统的文件系统是树

    您始终可以使用带标题的单个文件,并使用存储为无符号整数的字节偏移或映射到整数的值。在文件内部表示某个节点的开始...然后在每个节点的末尾都有一个记录结束。

    你也可以使用XML文件 引用其他位置或单个文件以及 XPath / XPointers

    <Node id="someNode">
        <value>...</value>
        <children>
            <child xpath="/node[id=1]" />
            <child xpath="/node[id=29]" />
    

    但这意味着如果它们只是二进制blob,则将值序列化为字符(eww)您的值可能是只写入文件的二进制块的路径,如:

    <value>/path/to/mappable.bin</value>
    

    检查从XML封装到用C编写的文件系统的任何内容 整个树的实现。

    此XML解决方案可能会膨胀,但如果您不需要速度,则非常简单。只是一个高级方法的例子。树存储是一个古老的问题,各个层面都有解决方案。

    树木是树木。

答案 2 :(得分:1)

二进制或文本是第一个问题

历史上,应用程序将复杂的二进制格式用于结构化数据,但目前的趋势是定义基于文本的表示,因为这会生成更多开发人员和用户友好的文件。

XML是作为持久化和交换结构化数据的可移植方式创建的。

如果是我,我会使用类似XML但不那么笨重的YAML。

如果文件可能变得非常大,那么你可以做OpenOffice所做的事情并将它们保存为基于文本的标记,但直接写入压缩文件(我认为它是OO的zip文件)存档。

大多数语言已经有序列化库;我确信有一些用于C的Boost库。通常有多个序列化接口使用不同的表示。

如果使用库,XML或YAML,则链接将隐含在树形结构表示中。如果您的数据有更通用的图表,那么 无论您使用文本还是二进制文件,都可能需要规范化链接。这是你提到的指针问题。解决它的一种方法是保留在读取或写入文件时使用的临时映射。也就是说,您只需命名每个链接目标,例如A1,A2,A3 ......然后将其用作目标处的标记,并将其用作源名称的链接名称(想想href =)。

我不会将文件偏移用作指针,它看起来太脆弱了,使用XML或YAML或其他已经存在的东西自然是有道理的。

答案 3 :(得分:1)

确切地说,存储指针值是没有意义的。

您应该创建一个文本或二进制格式,将数据保存在树形结构中 我建议阅读Nested Set Model,这是关于在关系数据库中存储树数据结构的另一个例子。

例如,这就是您的数据存储方式:

[meta-data][data]

[meta-data] = [ length ][ list-of-Nested-Set-Model-Locations ] [ list-of-data-records ] = [ lft-#1 ][ rgt-#1 ][ lft-#2 ][ rgt-#2 ] ... [data] = [length][ payload / data-itself ]

这只是一个例子,使用JSON(推荐)或XML可能更好&amp;更容易。

答案 4 :(得分:0)

是否可以对内存中的树进行分类?这听起来像是通过网络发送对象的常见java问题。对象引用了其他内容,但这些指针地址会在程序的地址空间之外发生变化。您可以将树序列化为XML或JSON格式吗?