可以懒惰地分配静态内存吗?

Emm*_*ess 6 c linux memory

在C程序中有一个静态数组:

#define MAXN (1<<13)
void f() {
    static int X[MAXN];
    //...
}
Run Code Online (Sandbox Code Playgroud)

在实际使用每个页面之前,Linux内核是否可以选择不将地址映射到物理内存?那么X怎么可以满0,那么当每个页面被访问时,内存是否归零?这怎么不影响程序的性能?

use*_*751 7

在实际使用每个页面之前,Linux内核是否可以选择不将地址映射到物理内存?

是的,它为所有内存执行此操作(除了驱动程序和内核本身使用的特殊内存).

那么X怎么可以满0,那么当每个页面被访问时,内存是否归零?

你应该忽略这个细节.只要当你访问它时内存充满了零,我们就说它充满了零.

这怎么不影响程序的性能?

确实如此.

  • "你应该忽略这个细节"但这是问题的有趣部分,因为C标准说所有具有静态存储持续时间的对象必须在调用main()之前初始化.除此之外,C没有任何限制. (3认同)
  • @Lundin:两个单词(或3?):as-if规则. (2认同)

Emm*_*ess 2

Linux 内核可以选择在实际使用每个页面之前不将地址映射到物理内存吗?

是的,对于用户空间内存,它总是可以完成。

那么X怎么会全是0呢,是不是每次访问页的时候内存都被清零了呢?

内核维护一个全0的页面,当用户请求静态数组的新页面(静态因此在第一次使用之前全0)时,内核提供清零的页面,但没有程序写入的权限。写入数组会触发写时复制机制:发生页面错误,然后内核分配一个可写页面,映射它并从最后一条指令(由于页面错误而无法完成的指令)恢复程序。过错)。请注意,预置零优化会更改此处的实现细节,但理论是相同的。

这如何不影响程序的性能?

程序不必在启动时将大量(可能)页面清零,并且内核实际上不必拥有内存(可以要求比系统拥有的内存更多的内存,只要您不使用它)。程序执行期间会产生页面错误,但可以将其最小化,请参阅mmap()madvise()MADV_SEQUENTIAL. 请记住,翻译后备缓冲区不是无限的,它可以维护很多条目。

资料来源:Linux 内存常见问题解答Alan Ott 的 Linux 内存管理简介