C中的别名内存

Alias memory in C

如果我有像这样的绳状数据结构:

struct rope {
  struct { char *buf; size_t len; } *segments;
  size_t len;
}

有没有办法将每个段的缓冲区连续映射到虚拟内存中 space,而无需复制?我的用例是以最有效的方式将绳索转换为字符串。

这是一个如何使用它的例子:

char *s = rope_flatten(r);
printf("%s\n", s);
r.segments[0].buf[4] = 'x';
printf("%s\n", s); // The 5th character is now replaced with 'x'

不用说,缓冲区(至少,映射的位)不会以 NUL 终止。

我知道这可能非常特定于平台。如果有符合 POSIX 的东西那就太棒了。如果没有,Linux 是我的主要目标,如果不支持,我可以回退到 malloc 和 memcpy。

在一个完美的世界中,您可以像往常一样创建您的绳索并再次重新映射每个段,这样您就可以看到它们是连续的第二个视图。如果您编辑一个片段,没问题,它会镜像到另一个视图。如果你放大一个段,缓冲区会透明地更新。

尽管有几个问题使这不可行:

  • 虚拟内存的粒度不是按字节而是按页,通常为 4KiB,并且它们被映射为一个整体。您的代码单元可能比那个小一点。
  • 添加和删除段仍需要页面 table 修改
  • 修改时必须调用内核来更新映射,这很容易使您希望获得的任何性能优势相形见绌。
  • 可移植性问题:API 是 OS 特定的。需要 MMU。与 VIVT 缓存结合使用时的有趣效果

尽管如此,仍有将多个视图映射到一个地址的用例space,即当数据发生变化但数据未发生变化时结构,就像环形缓冲区一样:

通常情况下,您必须在软件中实现环绕逻辑,但如果您之后直接重新映射环形缓冲区的页面,您将获得一个环形缓冲区,您可以 memcpy . GNU Radio 采用了这种机制,并且有一个不错的博客 post: https://www.gnuradio.org/blog/buffers/

博客 post 让我很好奇,所以我在 libvas 中重新实现了 Linux、Windows 和 macOS 的机制。喜欢的可以看看