C 静态变量和 Linux fork

10

你好,我创建了一个服务器程序,在接受套接字连接后fork出一个新的进程。 程序中定义了一些静态分配的全局变量。我的问题是在fork之后这些静态缓冲区会被分配两次吗?还是fork只会复制堆和调用栈上的地址空间?

4个回答

12

整个地址空间都被复制,包括所有全局变量和程序文本。


我正在使用大约10MB的RAM,并且在fork调用后没有看到可用内存量下降?如果静态分配发生在编译时,那么fork如何复制它? - eat_a_lemon
1
静态分配不会在编译时发生 - 它是在运行时发生的,其实现由所涉及的 C 库决定,但它必须在“main”执行之前完成。因此,内存是进程镜像的一部分,这就是 fork 复制的内容。 - user257111
8
当你调用fork()函数时,程序使用的内存仅仅是被标记为写时复制。因此,只有当你开始向内存中写入数据时,你的内存使用量才会开始上升,直到你写入的页面产生不共享的副本。 - btilly

8
整个地址空间在 fork(2)期间被“复制”。通常使用写时复制技术实现,关于共享程序文本和库的细节不重要。父进程和子进程都拥有自己的静态数据副本。

2

fork()函数会复制整个进程镜像。就是说,所有东西都会被复制一遍。因此,这些内容并不会被分配两次……它们只是在每个可执行镜像中分配一次,并且如果你在父进程中引用其中一个变量,与子进程中的变量不同,除非你使用共享内存。

关于static这个关键字,它的意思是(来自ISO C99):

标识符具有外部或内部链接的对象,或者使用存储类别说明符static声明的对象具有静态存储持续时间。其生存期是整个程序的执行时期,其存储值仅在程序启动之前初始化一次。

这基本上意味着你的缓冲区将作为CRT启动例程的一部分被初始化一次,只有当你退出时才会消失。在本例中,这个存储空间会在每个子进程退出时消失。


2

Linux使用一种称为写时复制的机制。这基本上意味着,只要变量没有被修改,父进程和新进程就共享一个变量。但在变量被修改之前,它会被复制,新进程使用副本。这是出于性能原因而进行的操作,并且该技术称为惰性优化。因此,您不必担心在一个进程中更改变量会在另一个进程中更改它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接