如果我有一个使用fork()并且可能被开发为多线程的应用程序,那么为安全地编程这种应用程序需要考虑哪些拇指规则/指南?
答案 0 :(得分:4)
根据(http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them,fork in multi-threaded program等各种互联网文章,基本的拇指规则是:
(Main)Process [0] Monothread - > fork() - > (子)进程[1]多线程:确定!
如果 Process [1] 在内存中崩溃或混乱,将 触及 Process [0] 的地址空间(除非您使用共享R / W内存......但这是它自己的另一个主题。)在Linux中,默认情况下所有 fork()ed 内存都是Copy On Write。鉴于 Process [0] 是单线程的,当我们调用 fork()时,所有可能的互斥原语应该一般在解锁州。
(Main)Process [0] Multithreaded - > fork() - > (孩子)过程[1]单声道/多线程:坏!
如果您使用 fork()多线程进程,则您的互斥锁和许多其他线程同步原语可能会在进程[1]中处于未定义状态。你可以使用 pthread_atfork()来解决这个问题,但如果你使用图书馆,你也可以掷骰子,希望能够幸运。因为通常你不(想)知道库的实现细节。
fork()在多线程进程中的优势在于,您可以更快地操作/读取/聚合数据(在子进程中),而无需关心进程的稳定性<来自(Main)的em> fork()。如果您的主进程具有很多内存的数据集,并且您不想复制/重新加载它以安全地处理另一个进程(Child)中的数据,那么这非常有用。这样原始进程就可以稳定并独立于数据聚合/操作过程( fork()ed )。
当然,这意味着原始进程通常比以多线程方式开发时更慢。但同样,这是您可能希望为更稳定而付出的代价。
如果您的主进程是多线程的,则避免使用 fork()。以稳定的方式实现它将是适当的混乱。
干杯
答案 1 :(得分:-1)
在Linux上,线程是根据进程实现的。换句话说,线程实际上只是一个fork()
,主要是共享内存,而不是完全写入时复制内存。这意味着,当你在一个线程(主要或其他)中使用fork()
时,你最终会复制所有线程的整个共享内存空间,以及你调用的线程的线程特定存储空间{{ 1}}来自。
现在所有这些听起来都不错,但这并不意味着这将会发生或运作良好。如果要创建克隆进程,请在启动任何其他线程之前尝试执行fork,然后使用只读虚拟内存使分叉进程与当前内存值保持同步。
所以虽然它可能有用,但我只是建议测试,并尝试先找到另一种方法。并做好了很多准备:
fork()