当一个进程分叉时,共享库.so还会在地址空间吗?并且构造函数会再次执行吗?

Win*_*ser 6 c linux multithreading fork process

当进程分叉时,子进程是否会在其地址空间中具有自定义共享库(.so文件)?

如果是这样,共享库的地址是否与其父进程相同或不同(由于ASLR)?

__attribute__ ((constructor)) constructor在所有子进程中,在main函数之前运行的函数是否会再次执行?线程怎么样?

Chr*_*ton 6

是的,孩子将保留父母的映射.通常,Linux的虚拟内存系统实际上将共享两个进程之间的页面,直到任何一个尝试写入新数据.此时,将创建一个副本,每个进程将拥有自己的唯一版本 - 在不同的物理地址但保留相同的虚拟地址.这被称为"写入时复制",并且与不能支持此功能的系统相比,具有显着的效率和资源优势,尤其是经常运行的运行代码.

地址空间布局随机化(ASLR)不能应用已经分配了虚拟地址的库或对象,因为这样做会破坏代码中任何位置的任何指针 - 运行非托管代码的系统无法知道即将占到.

由于所有先前构造的对象已经存在于内存中,因此仅仅因为fork而不再调用构造函数.由于它们被唯一修改而需要复制的任何对象都是由幕后的VM系统无形地完成的 - 它们并不真正知道它们是被克隆的,并且你很可能最终得到一对对象部分实现继续共享具有相同内容的物理页面,而另一部分已无形地分成不同的物理页面,每个进程具有不同的内容.

你还询问了线程,这是一个事情变得复杂的领域.通常,只有调用fork()的线程才会以实时形式存在于子节点中(尽管属于其他节点的数据将存在于共享映射中,因为无法知道可能与分叉线程共享的内容).如果您需要尝试分叉多线程程序,则需要查看线程实现的文档.对于Linux上常见的pthreads实现,特别要注意pthread_atfork()