Linux中的线程与进程
我最近听到一些人说,在Linux中,使用进程而不是线程几乎总是更好,因为Linux在处理进程方面非常高效,并且因为与线程关联的问题太多(如锁定)。 但是,我很怀疑,因为在某些情况下,线程似乎可以带来相当大的性能提升。
所以我的问题是,当遇到线程和进程都可以很好处理的情况时,我应该使用进程还是线程? 例如,如果我正在编写Web服务器,是否应该使用进程或线程(或组合)?
Linux使用1-1线程模型,(对于内核)进程和线程之间没有区别 - 一切都只是一个可运行的任务。 *
在Linux上,系统调用clone
任务,具有可配置的共享级别,其中包括:
CLONE_FILES
:共享相同的文件描述符表(而不是创建副本) CLONE_PARENT
:不要在新任务和旧任务之间建立父 - 子关系(否则,孩子的getppid()
=父母的getpid()
) CLONE_VM
:共享相同的内存空间(而不是创建COW副本) fork()
调用clone(
最少共享)
和pthread_create()
调用clone(
大多数共享)
。 **
因为复制表和为内存创建COW映射, fork
成本要比pthread_create
ing多一点,但Linux内核开发人员已经尝试(并成功)将这些成本降到最低。
如果任务之间切换,如果它们共享相同的内存空间和各种表格,将比不共享时便宜一点,因为数据可能已经加载到缓存中。 然而,即使没有共享任务,切换任务仍然非常快 - 这是Linux内核开发人员试图确保(并成功确保)的其他内容。
实际上,如果您使用的是多处理器系统, 则不共享可能实际上有利于性能:如果每个任务都在不同的处理器上运行,则同步共享内存会很昂贵。
*简化。 CLONE_THREAD
会导致信号传递被共享(这需要共享信号处理程序表的CLONE_SIGHAND
)。
**简化。 存在两种SYS_fork
和SYS_clone
系统调用,但内核, sys_fork
和sys_clone
都是围绕相同的两个非常薄的包装do_fork
功能,这本身就是围绕瘦包装copy_process
。 是的,术语process
, thread
和task
在Linux内核中可以互换使用。
Linux(甚至Unix)为你提供了第三种选择。
选项1 - 流程
创建一个独立的可执行文件,用于处理应用程序的某些部分(或全部),并为每个进程单独调用它,例如,该程序运行其自身的副本以将任务委托给。
选项2 - 线程
创建一个独立的可执行文件,它使用单个线程启动并创建其他线程来完成某些任务
选项3 - 叉
只有在Linux / Unix下可用,这有点不同。 分叉进程真的是它自己的进程,拥有自己的地址空间 - 孩子通常不会影响其父代或同级地址空间(与线程不同),因此您可以增加健壮性。
但是,内存页面不会被复制,它们是写入时复制的,因此通常使用的内存通常比您想象的要少。
考虑一个由两个步骤组成的Web服务器程序:
如果你使用线程,第1步将完成一次,第2步在多个线程中完成。 如果您使用“传统”进程,则需要为每个进程重复执行步骤1和2,并且用于存储配置和运行时数据的内存重复。 如果使用fork(),则可以执行第1步,然后执行fork(),将运行时数据和配置保留在内存中,不会被复制。
所以有三个选择。
这取决于很多因素。 进程比线程更重,并且具有更高的启动和关闭成本。 进程间通信(IPC)也比线程间通信更困难和更慢。
相反,进程比线程更安全,更安全,因为每个进程都在自己的虚拟地址空间中运行。 如果一个进程崩溃或者有一个缓冲区溢出,它根本不会影响任何其他进程,而如果一个线程崩溃,它会关闭进程中的所有其他线程,并且如果线程缓冲区溢出,它将打开所有线程中都有一个安全漏洞。
因此,如果您的应用程序的模块可以通过少量通信独立运行,那么如果您能承担启动和关闭成本,则应该使用进程。 IPC的性能受到的影响会很小,并且您会对漏洞和安全漏洞稍微安全一些。 如果您需要获得每一点性能,或者拥有大量共享数据(例如复杂的数据结构),请使用线程。
链接地址: http://www.djcxy.com/p/92159.html上一篇: Threads vs Processes in Linux
下一篇: Cancelling a thread that has a mutex locked does not unlock the mutex