当进程分叉时,共享库.so是否还在地址space?构造函数会再次执行吗?

When a process forks, would the shared library .so still in the address space? And would the constructor be executed again?

进程fork时,子进程会不会在地址space中有自定义的共享库(.so文件)?

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

主函数__attribute__ ((constructor)) constructor之前的函数运行是否会在所有子进程中再次执行?线程呢?

是的,子项将保留父项的映射。通常,Linux 的虚拟内存系统实际上会在两个进程之间共享页面,直到其中一个尝试写入新数据为止。届时,将制作一个副本,每个进程将拥有自己唯一的版本 - 在不同的 物理 地址但保留相同的 虚拟 地址.这被称为 "copy on write" 并且比不支持它的系统具有显着的效率和资源优势,特别是 运行 经常分叉的代码。

地址 Space 布局随机化 (ASLR) 不能应用于已分配虚拟地址的库或对象,因为这样做会破坏代码中任何位置的任何指针 - 系统 运行 非托管代码对解释的了解不够。

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

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