在我一直在阅读的手册页中,似乎popen,system等倾向于调用fork()。反过来,fork()复制进程的整个内存状态。这看起来非常沉重,特别是在很多情况下,来自fork()调用的子节点使用的内存很少(如果有的话)。
所以,我的问题是,我可以获得fork()之类的行为,而不会复制父进程的整个内存状态吗?或者是否有一些我缺少的东西,这样fork()并不像看起来那么重(比如,可能会调用优化以避免不必要的内存重复)?
答案 0 :(得分:6)
fork(2)和所有syscalls一样,是一个原始操作(但有些C库使用clone(2))。主要是从一个机器指令SYSCALL
或SYSENTER
切换到用户模式到内核模式,然后(最近版本的)Linux内核正在进行非常重要的处理。
实际上它非常有效(例如,小于一毫秒,有时甚至不到十分之一),因为内核广泛使用惰性copy-on-write技术在父和子之间共享页面。子进程。当覆盖共享页面时,实际复制将在page faults之后发生。
并且forking具有巨大的优势,因为其他一些程序的启动被委托给execve(2):它在概念上 简单:父和子之间的唯一区别子进程是fork
关于POSIX系统(如Linux,fork(2)或合适的clone(2)等效物的BTW)是唯一的创建流程的方式(有一些奇怪的例外,你应该通常忽略:内核正在制作一些像/sbin/init
等的进程...),因为vfork(2)已经过时了。
答案 1 :(得分:2)
问题是要运行标准链接的可执行文件的main函数,需要调用execve
,exec替换整个过程映像,因此需要一个新的地址空间,这就是{{1是的。
您可以通过让您的calee在共享库中公开其fork
功能(但不能将其称为main)来解决这个问题,然后您可以加载具有main
功能的函数无需分叉(假设没有符号冲突)。
这将是main
的更有效的替代方案(基本上具有函数调用的效率)。
现在system
涉及管道并使用管道,管道以不同的可调度单位结束。使用相同地址空间的线程可以在这里用作单独进程的较轻替代方案。