进程和线程之间的技术区别是什么?
我感觉像“进程”这样的词被过度使用了,而且还有硬件和软件线程。像Erlang这样的语言中的轻量级进程怎么样?是否有明确的理由使用一个术语而不是另一个术语?
进程和线程之间的技术区别是什么?
我感觉像“进程”这样的词被过度使用了,而且还有硬件和软件线程。像Erlang这样的语言中的轻量级进程怎么样?是否有明确的理由使用一个术语而不是另一个术语?
当前回答
尝试从Linux内核的OS视图回答
程序在启动到内存中时成为一个进程。进程有自己的地址空间,这意味着在内存中有各种段,例如用于存储编译代码的.text segment,用于存储未初始化的静态或全局变量的.bss等。每个进程都有自己的程序计数器和用户空间堆栈。在内核内部,每个进程都有自己的内核堆栈(由于安全问题,它与用户空间堆栈分离)和一个名为task_struct的结构,该结构通常被抽象为进程控制块,存储有关进程的所有信息,例如其优先级、状态(以及大量其他块)。一个进程可以有多个执行线程。
对于线程,它们驻留在一个进程内,并与线程创建过程中可以传递的其他资源(如文件系统资源、共享挂起的信号、共享数据(变量和指令))共享父进程的地址空间,从而使线程轻量级,从而允许更快的上下文切换。在内核内部,每个线程都有自己的内核堆栈以及定义线程的task_struct结构。因此,内核将同一进程的线程视为不同的实体,并且它们本身是可调度的。同一进程中的线程共享一个称为线程组id(tgid)的公共id,它们也有一个名为进程id(pid)的唯一id。
其他回答
http://lkml.iu.edu/hypermail/linux/kernel/9608/0191.html
莱纳斯·托瓦尔兹(torvalds@cs.helsinki.fi)1996年8月6日星期二12:47:31+0300(欧洲东部夏令时)邮件排序依据:[date][thread][subject][author]下一条消息:Bernd P.Ziller:“回复:get_hash_table中的错误”上一条消息:Linus Torvalds:“Re:I/O请求排序”1996年8月5日星期一,Peter P.Eiserloh写道:我们需要明确线程的概念。太多人了似乎混淆了线程和进程。以下讨论不反映linux的当前状态,而是试图保持高级别的讨论。不!没有理由认为“线程”和“进程”是独立实体。这是传统的做法,但我我个人认为这样想是一个重大错误。唯一的有理由认为这种方式是历史包袱。线程和进程实际上只是一件事:试图人为地区分不同的案例只是自我限制。一个“执行环境”,这里称为COE,只是一个企业集团该状态包括CPU等状态(寄存器等)、MMU状态(页面映射)、权限状态(uid、gid)和各种“通信状态”(打开文件、信号处理器等)。传统上,“线程”和“进程”主要是指线程具有CPU状态(+可能一些其他最小状态),而所有其他上下文都来自过程然而,这只是一种划分COE总状态的方法,没有任何东西表明这是正确的方法。限制自己对那种形象来说简直是愚蠢至极。Linux对此的思考方式(以及我希望的工作方式)是没有所谓的“进程”或“线程”。有只有整个COE(Linux称为“任务”)。不同的COE可以彼此共享部分上下文共享是传统的“线程”/“进程”设置,但应该真正被视为仅仅是一个子集(它是一个重要的子集,但是这种重要性不是来自设计,而是来自标准:我们显然希望在Linux上运行符合标准的线程程序也是)。简而言之:不要围绕线程/进程的思维方式进行设计。这个内核应该围绕COE的思维方式进行设计,然后pthread库可以将有限的pthread接口导出给用户他们想用这种方式来看待COE。作为一个例子,当你认为COE是与线程/进程相反:您可以执行外部“cd”程序,这在UNIX和/或进程/线程中传统上是不可能的(愚蠢的例子,但想法你可以拥有这些类型的“模块”传统的UNIX/threads设置)。执行以下操作:克隆(clone_VM|clone_FS);child:execve(“外部cd”);/*“execve()”将解除VM的关联,因此使用CLONE_VM是为了更快地进行克隆*/您可以自然地执行“vfork()”(它需要最少的内核支持,但这种支持完全符合CUA的思维方式):克隆(clone_VM);child:继续运行,最终执行()妈妈:等高管您可以执行外部“IO deamons”:克隆(clone_FILES);child:打开文件描述符等妈妈:用孩子打开的fd和vv。以上所有的工作都是因为您没有绑定到线程/进程思维方式。以web服务器为例,其中CGI脚本作为“执行线程”完成。你不能用传统线程,因为传统线程总是必须共享整个地址空间,所以你必须链接所有你曾经希望在web服务器本身(一个“线程”不能运行另一个可执行)。将此视为“执行上下文”问题任务现在可以选择执行外部程序(=将来自父级的地址空间)等,或者他们可以示例与父级共享除文件之外的所有内容描述符(这样子“线程”可以打开大量文件家长需要担心它们:当子“线程”退出,并且不会使用父级中的fd)。例如,设想一个线程化的“inetd”。你想要低开销fork+exec,所以用Linux的方式可以代替使用“fork()”您编写了一个多线程inetd,其中每个线程都是用仅CLONE_VM(共享地址空间,但不共享文件描述符等等)。然后,如果它是外部服务(rlogind,例如),或者可能是内部inetd服务之一(echo,timeofday)在这种情况下,它只是做它自己的事情,然后退出。你不能用“线程”/“进程”这样做。莱纳斯牌手表
流程:
进程基本上是一个正在执行的程序。它是一个活跃的实体。一些操作系统使用术语“任务”来指代正在执行的程序。进程总是存储在也称为主存储器或随机存取存储器的主存储器中。因此,流程被称为活动实体。如果重新启动机器,它将消失。多个进程可以与同一程序相关联。在多处理器系统上,可以并行执行多个进程。在单处理器系统上,虽然没有实现真正的并行性,但应用了进程调度算法,处理器被调度为每次执行一个进程,从而产生并发的错觉。示例:执行“计算器”程序的多个实例。每个实例都称为一个过程。
线程:
线程是进程的子集。它被称为“轻量级进程”,因为它类似于真实进程,但在进程的上下文中执行,并共享内核分配给进程的相同资源。通常,一个进程只有一个控制线程——一次执行一组机器指令。进程也可以由并发执行指令的多个执行线程组成。多个控制线程可以利用多处理器系统上可能的真正并行性。在单处理器系统上,应用线程调度算法,并调度处理器每次运行一个线程。进程中运行的所有线程共享相同的地址空间、文件描述符、堆栈和其他与进程相关的属性。由于进程的线程共享相同的内存,因此在进程内同步对共享数据的访问变得空前重要。
参考-https://practice.geeksforgeeks.org/problems/difference-between-process-and-thread
进程和线程的真实示例这将为您提供有关线程和进程的基本信息
我从Scott Langham的回答中借用了上述信息-谢谢
同一进程中的线程共享内存,但每个线程都有自己的堆栈和寄存器,线程在堆中存储线程特定的数据。线程从不独立执行,因此与进程间通信相比,线程间通信要快得多。
进程从不共享相同的内存。当子进程创建时,它会复制父进程的内存位置。进程通信通过使用管道、共享内存和消息解析来完成。线程之间的上下文切换非常缓慢。
来自嵌入式世界,我想补充一点,进程的概念只存在于具有MMU(内存管理单元)的“大型”处理器(台式CPU、ARM Cortex A-9)和支持使用MMU的操作系统(如Linux)中。对于小型/老式处理器和微控制器以及小型RTOS操作系统(实时操作系统),如freeRTOS,没有MMU支持,因此没有进程,只有线程。
线程可以访问彼此的内存,并且它们由OS以交错的方式调度,因此它们看起来是并行运行的(或者对于多核线程,它们实际上是并行运行)。
另一方面,进程则生活在由MMU提供和保护的私有虚拟内存沙盒中。这很方便,因为它可以:
防止错误进程导致整个系统崩溃。通过使其他流程数据不可见和无法访问。进程内的实际工作由一个或多个线程负责。