产生新进程v线程的动机

时间:2011-04-30 04:30:44

标签: c multithreading process

据我所知,如果您的程序具有可以并行执行的大段,那么当实例不受单个资源绑定时,生成新线程将是有益的。例如,Web服务器发出页面请求。

从线程间通信成本低得多且上下文切换更快的方面来看,线程是有益的。

进程可以从一个进程无法“混乱”另一个进程内容的方面为您提供更多安全性,而如果一个线程崩溃,则所有线程可能会在所述进程内崩溃。

我的问题是,您希望何时使用某个流程(例如C中的fork())有哪些示例?

我可以想到,如果你有一个想要启动另一个程序的程序,将它封装在一个新进程中是有意义的,但我觉得我错过了启动一个新进程的一些更大的理由。

具体来说,什么时候有一个程序产生一个新的进程vs线程?

3 个答案:

答案 0 :(得分:3)

使用进程的主要原因是进程可能崩溃或发疯,操作系统将限制其对其他进程的影响。因此,例如,Firefox最近开始在不同的流程中运行插件,IIRC Chrome在不同的流程中运行不同的页面,并且Web服务器在很长一段时间内在不同的流程中处理了各个请求。

操作系统应用限制的方式有几种:

  • 崩溃 - 正如您所注意到的,如果线程崩溃,通常会占用整个过程。这激发了浏览器进程的界限:浏览器和浏览器插件是受到持续攻击的复杂代码,因此采取不同寻常的预防措施是有意义的。
  • 资源限制。如果进程中的某个线程打开了大量文件,分配了大量内存等,那么它会影响到你。另一个过程不需要,因为它可以单独限制。因此,Web服务器中的每个请求的资源使用可能比整个服务器更受限制,因为您希望服务器同时提供多个请求,而不会有任何远程用户占用资源。
  • 能力。因操作系统而异,但仅举例来说,您可以在chroot jail中运行一个进程,以确保它不会修改或读取它不应该的文件,无论您的代码对漏洞有多么容易受到攻击。再举一个例子,SymbianOS有一个明确的权限列表,可以对系统做各种事情(“读取用户电话簿”,“写入用户电话簿”,“解密DRM文件”等)。没有办法放弃你的进程拥有的权限,所以如果你想做一些高度敏感的事情,然后再回到低敏感度模式,你需要一个进程边界。想要这样做的一个原因是安全性 - 可能包含安全漏洞的未知代码或代码可能会有些沙盒化,而不受限制的少量代码可能会受到更严格的审查。另一个原因是让操作系统强制执行您设计的某些方面。
  • 驱动。通常,设备驱动程序控制对唯一系统资源的共享访问。与功能一样,限制对单个驱动程序进程的访问意味着您可以禁止它访问所有其他进程。例如,Windows上的IIRC TrueCrypt安装了一个驱动程序,该驱动程序具有增强的权限,允许它注册带有驱动器号的加密容器,然后像任何其他Windows文件系统一样运行。应用程序的GUI部分以常规用户模式运行。我不确定Windows上的文件系统驱动程序是否确实需要一个关联的进程,但一般情况下设备驱动程序可能会这样做,所以即使这不是一个很好的例子,希望它能给出这个想法。

使用流程的另一个潜在原因是它可以更容易地推理您的代码。在多线程代码中,您依赖所有类的不变量来推断对特定对象的访问是序列化的:如果您的代码不是多线程的,那么您知道它是[*]。当然,也可以使用多线程代码执行此操作,只需确保您知道每个对象“拥有”哪个线程,并且永远不会从不是其所有者的线程访问对象。流程边界强制执行此操作,而不仅仅是为其设计。同样,不确定这是动机,但是例如World Community Grid客户端可以使用多个核心。在该模式下,它运行多个进程,每个进程具有完全不同的任务,因此它具有额外内核的性能优势,无需任何单个任务需要可并行化,或任何需要线程安全的任务的代码。

[*]好吧,只要它不是在共享内存中创建的。您还需要避免意外的递归调用等,但这通常比同步多线程代码更简单。

答案 1 :(得分:0)

线程与同一进程中的其他线程共享相同的内存。因此,如果您想要将数据从一个线程传递到另一个线程,您必须处理锁定,同步等问题,这是复杂且有缺陷的事情,应该避免。如果其中一个线程崩溃,它将导致整个过程。与创建新流程相反,创建线程很轻松。

在每个任务的单独进程中,专业人员是您不需要担心需要锁定和同步的共享可变数据,因为您将使用消息传递与进程通信,即使进程崩溃不会取消整个应用程序(浏览器会做到这一点:每个选项卡=新进程)。缺点是流程创建比线程创建更重。请记住,这些单独的进程可能有多个线程。

因此,使用上述要点,您可以为您的特定应用选择最佳方法。没有银弹,这完全取决于具体情况。

要记住的一点是,在这两种情况下,您都应该使用“池”(线程池和进程池),而不是为要执行的每个任务创建新的线程/进程。 浏览器示例:每个选项卡都有自己的进程不使用池,因为在这种情况下进程不是“工作进程”,应该等待主进程给他们一些任务然后再完成后进入等待状态。

答案 2 :(得分:0)

我会说线程有一个有限的堆栈,这可以限制你可以继续使用它们的工作量。 BOT OTH您可以使用共享内存和线程消息非常简单地交换数据。拥有10个线程,每个线程执行一项简单的任务,即使在基线计算机上也很容易管理。

在我看来,使用流程更难管理,因为您必须处理父级和子级之间的数据传输。您必须使用管道,消息队列等...并且内存传输比线程更昂贵。停止流程涉及发送SIG_KILL。你得到了崩溃安全性:进程崩溃不会占用你的主要应用程序。

帖子示例
- I / O读/写处理:您传递缓冲区,线程在写/读完成时通知您 - 矩阵乘法:您可以按行或列拆分矩阵计算,任务非常简单

流程示例
- 使用一些复杂的压缩将一些数据导出为图像格式 - 索引器流程,收集元数据并将其格式化为应用程序的内部格式 - 复杂应用程序的每个新绘图窗口

<强> TL;博士
恕我直言:
- 如果任务复杂,请使用进程 - 如果拍摄很轻,请使用线程