声明 16GB BSS 段有什么缺点吗?

问题描述 投票:0回答:1

我正在查看这个小程序,其中内存使用情况是不可预测的,因为它运行的目录可能包含很少的文件或可能超过数千万个文件,并且由于内核的原因需要将所有文件名一次存储在 RAM 中行为。

这段代码不是我正在编写的程序。这说明了为什么我必须一次将所有文件名存储在内存中:

   DIR *dir = opendir(".");
   for (struct dirent *entry; (entry = readdir(dir);)
       unlink(entry->d_name); // DANGER DO NOT RUN ME

此代码片段看起来像是从当前目录中删除了所有文件,但事实并非如此。现代系统的根本问题是,当您执行此类操作时,您会丢失文件,因为删除或更改目录树条目会破坏枚举的稳定性。

几乎整个程序的内存必须由一个包含目录中所有文件名的缓冲区组成,因此我正在考虑声明一个如下所示的内存结构(ASLR 为 on 所以 0 并不是真正的 0 ):

000000000 ELF header
000000118 Program code
000001000 work buffers
000002000 begin stretchy array
400002000 no man's land (mapped with 0 access so anything hitting it faults)
400003000 top of stack
400005000 bottom of stack

以下情况无需讨论:程序代码太小或堆栈太小。这些常数很容易改变。

需要讨论的是大弹性阵列。管理不连续的数组会很臃肿,而且我们有一个 MMU,因此它不需要在物理内存中是连续的。我很久以前就在一个不必关心的系统上看到过这个技巧,因为它是单用户的。我不知道这是否会在多用户盒子上引起问题。

我想要的行为应该是显而易见的。内存在被触及之前不会被分配。到那时,就什么都不是了。那么,说我有 16GB BSS 段并且只使用我实际需要的东西有多糟糕?由于它太大了,我需要绝对确定堆栈不会遇到它,因此使用

mmap()
动态分配地址空间是不可能的。

替代假设:理论上,如果有办法以 PE 格式表示,我可以在启动时保留内存,并根据需要进行 mmap 提交。根据手册页,没有办法说在 mmap 中保留 16GB 地址空间并且实际上尚未分配任何地址空间。

我已经用空程序写下了 ELF 标头 (

mov al, 60 ; syscall
),因此它确实可以运行。

linux elf virtual-memory
1个回答
0
投票

即使您将整个目录读入内存,也无法保证防止该目录的并发修改。

请参阅 https://stackoverflow.com/a/2938387/131433,了解在目录 fd 上使用 fsync 的建议,这似乎允许您在没有特殊 BSS 的情况下读取它们,并且仍然避免并发问题。

© www.soinside.com 2019 - 2024. All rights reserved.