进程和线程之间的技术差异是什么?
我感觉像'过程'这样的词被过度使用,还有硬件和软件线程.如Erlang这样的语言轻量级进程怎么样?是否有明确的理由使用一个术语而不是另一个术语?
进程和线程都是独立的执行序列.典型的区别在于(同一进程的)线程在共享内存空间中运行,而进程在不同的内存空间中运行.
我不确定你可能指的是什么"硬件"与"软件"线程.线程是一种操作环境功能,而不是CPU功能(尽管CPU通常具有使线程高效的操作).
Erlang使用术语"进程",因为它不公开共享内存多道程序模型.将它们称为"线程"意味着它们共享内存.
流程
每个流程都提供执行程序所需的资源.进程具有虚拟地址空间,可执行代码,系统对象的打开句柄,安全上下文,唯一进程标识符,环境变量,优先级类,最小和最大工作集大小以及至少一个执行线程.每个进程都使用单个线程启动,通常称为主线程,但可以从其任何线程创建其他线程.
线程
线程是进程中可以调度执行的实体.进程的所有线程共享其虚拟地址空间和系统资源.此外,每个线程都维护异常处理程序,调度优先级,线程本地存储,唯一线程标识符以及系统将用于保存线程上下文直到调度的一组结构.线程上下文包括线程的机器寄存器集,内核堆栈,线程环境块和线程进程的地址空间中的用户堆栈.线程也可以有自己的安全上下文,可用于模拟客户端.
在MSDN上找到了这个:
关于进程和线程
Microsoft Windows支持抢占式多任务处理,它可以创建从多个进程同时执行多个线程的效果.在多处理器计算机上,系统可以同时执行与计算机上的处理器一样多的线程.
处理:
程序的执行实例称为进程.
某些操作系统使用术语"任务"来指代正在执行的程序.
进程始终存储在主存储器中,也称为主存储器或随机存取存储器.
因此,过程被称为活动实体.如果重新启动机器,它会消失.
几个过程可以与同一个程序相关联.
在多处理器系统上,可以并行执行多个进程.
在单处理器系统上,虽然没有实现真正的并行性,但是应用了进程调度算法,并且处理器被安排为一次执行一个进程,产生并发错觉.
示例:执行"计算器"程序的多个实例.每个实例都被称为一个过程.
线:
线程是进程的子集.
它被称为"轻量级进程",因为它类似于实际进程,但在进程的上下文中执行,并共享内核分配给进程的相同资源.
通常,进程只有一个控制线程 - 一次执行一组机器指令.
进程也可以由同时执行指令的多个执行线程组成.
多个控制线程可以利用多处理器系统上可能的真正并行性.
在单处理器系统上,应用线程调度算法,并且计划处理器一次运行一个线程.
进程内运行的所有线程共享相同的地址空间,文件描述符,堆栈和其他与进程相关的属性.
由于进程的线程共享相同的内存,因此在进程内同步对共享数据的访问会获得前所未有的重要性.
我从Knowledge Quest借用了上述信息!博客.
首先,让我们看一下理论方面.您需要了解流程在概念上是什么来理解流程和线程之间的区别以及它们之间共享的内容.
我们从第2.2.2节Tanenbaum的现代操作系统3e中的经典线程模型中得到以下结论:
流程模型基于两个独立的概念:资源分组和执行.有时将它们分开是有用的; 这是线程进来的地方....
他继续:
查看流程的一种方法是将相关资源组合在一起.进程具有包含程序文本和数据以及其他资源的地址空间.这些资源可能包括打开文件,子进程,待处理警报,信号处理程序,记帐信息等.通过以流程的形式将它们组合在一起,可以更容易地管理它们.进程的另一个概念是执行线程,通常缩写为只是线程.该线程有一个程序计数器,用于跟踪下一个要执行的指令.它有寄存器,它保存当前的工作变量.它有一个堆栈,其中包含执行历史记录,每个过程调用一个帧但尚未返回.虽然线程必须在某些进程中执行,线程及其过程是不同的概念,可以单独处理.流程用于将资源组合在一起; 线程是计划在CPU上执行的实体.
再向下,他提供了下表:
Per process items | Per thread items ------------------------------|----------------- Address space | Program counter Global variables | Registers Open files | Stack Child processes | State Pending alarms | Signals and signal handlers | Accounting information |
我们来处理硬件多线程问题.传统上,CPU将支持单个执行线程,通过单个程序计数器和寄存器组维护线程的状态.但是如果有缓存未命中会发生什么?从主内存获取数据需要很长时间,而在发生这种情况时,CPU只是闲置在那里.所以有人有想法基本上有两组线程状态(PC +寄存器),这样另一个线程(可能在同一个进程中,可能在不同的进程中)可以在另一个线程在主内存上等待时完成工作.这个概念有多个名称和实现,例如HyperThreading和Simultaneous Multithreading(简称SMT).
现在让我们来看看软件方面.在软件方面,线程基本上有三种实现方式.
用户空间线程
内核线程
两者的结合
实现线程所需要的只是能够保存CPU状态并维护多个堆栈,这在很多情况下可以在用户空间中完成.用户空间线程的优点是超快速的线程切换,因为您不必陷入内核并能够按照您喜欢的方式调度线程.最大的缺点是无法阻塞I/O(这会阻塞整个进程及其所有用户线程),这是我们首先使用线程的一个重要原因.在许多情况下,使用线程阻止I/O大大简化了程序设计.
除了将所有调度问题留给操作系统之外,内核线程还具有能够使用阻塞I/O的优点.但是每个线程切换都需要陷入内核,这可能相对较慢.但是,如果由于I/O阻塞而切换线程,这实际上不是问题,因为I/O操作可能已经将您困在内核中了.
另一种方法是将两者结合,多个内核线程各自具有多个用户线程.
回到你的术语问题,你可以看到一个过程和一个执行的线程是两个不同的概念,你选择使用哪个术语取决于你所谈论的内容.关于"轻量级过程"这个术语,我个人没有看到它的重点,因为它并没有真正传达正在发生的事情以及术语"执行线程".
解释有关并发编程的更多信息
进程具有自包含的执行环境.进程通常具有完整的私有基本运行时资源集; 特别是,每个进程都有自己的内存空间.
线程存在于进程中 - 每个进程至少有一个进程.线程共享进程的资源,包括内存和打开文件.这使得有效但可能有问题的通信成为可能.
记住普通人,
在您的计算机上,打开Microsoft Word和Web浏览器.我们称这两个过程.
在Microsoft Word中,您键入一些内容并自动保存.现在,你会发现编辑和保存并行发生 - 在一个线程上编辑并保存在另一个线程上.
应用程序由一个或多个进程组成.最简单的过程是一个执行程序.一个或多个线程在进程的上下文中运行.线程是操作系统分配处理器时间的基本单元.线程可以执行进程代码的任何部分,包括当前由另一个线程执行的部分.光纤是执行单元,必须由应用程序手动调度.光纤在调度它们的线程的上下文中运行.
从这里偷来了.
进程是代码,内存,数据和其他资源的集合.线程是在进程范围内执行的一系列代码.您(通常)可以在同一进程中同时执行多个线程.
进程和线程的真实示例 这将为您提供有关线程和进程的基本概念
我从Scott Langham的答案中借用了上述信息 - 谢谢
每个进程都是一个线程(主线程).
但每个线程都不是一个过程.它是流程的一部分(实体).
处理:
过程是一个沉重的过程.
流程是一个单独的程序,具有独立的内存,数据,资源等.
使用fork()方法创建进程.
在该过程之间切换上下文是耗时的.
示例:
说,打开任何浏览器(mozilla,Chrome,IE).此时,新进程将开始执行.
主题:
线程是轻量级进程.线程是在进程内捆绑的.
线程有共享内存,数据,资源,文件等.
线程是使用clone()方法创建的.
线程之间的上下文切换不像Process那么耗时.
示例:
在浏览器中打开多个选项卡.
线程和进程都是OS资源分配的原子单元(即,存在描述CPU时间如何在它们之间划分的并发模型,以及拥有其他OS资源的模型).区别在于:
共享资源(线程按定义共享内存,它们除了堆栈和局部变量之外没有任何其他内容;进程也可以共享内存,但是有一个单独的机制,由OS维护)
分配空间(进程的内核空间与线程的用户空间)
上面的Greg Hewgill关于"过程"这个词的Erlang含义是正确的,这里讨论了为什么Erlang可以做轻量级的过程.
进程和线程都是独立的执行序列.典型的区别在于(同一进程的)线程在共享内存空间中运行,而进程在不同的内存空间中运行.
处理
是一个正在执行的程序.它有文本部分,即程序代码,当前活动由程序计数器的值和处理器寄存器的内容表示.它还包括包含临时数据(如函数参数,返回地址和局部变量)的进程堆栈,以及包含全局变量的数据部分.进程还可以包括堆,该堆是在进程运行时期间动态分配的内存.
线
线程是CPU利用率的基本单位; 它包括线程ID,程序计数器,寄存器组和堆栈.它与属于同一进程的其他线程共享其代码段,数据段和其他操作系统资源,如打开文件和信号.
- 来自Galvin的操作系统
试图回答与Java世界有关的这个问题.
进程是程序的执行,但是线程是进程内的单个执行序列.进程可以包含多个线程.线程有时被称为轻量级进程.
例如:
示例1:JVM在单个进程中运行,JVM中的线程共享属于该进程的堆.这就是几个线程可以访问同一个对象的原因.线程共享堆并拥有自己的堆栈空间.这是一个线程调用方法及其局部变量的方式与其他线程保持线程安全的方式.但是堆不是线程安全的,必须同步才能保证线程安全.
示例2:程序可能无法通过读取击键来绘制图片.该程序必须充分注意键盘输入,并且缺乏一次处理多个事件的能力将导致麻烦.解决此问题的理想方法是同时无缝地执行程序的两个或多个部分.线程允许我们这样做.这里绘制图片是一个过程,阅读按键是子过程(线程).
http://lkml.iu.edu/hypermail/linux/kernel/9608/0191.html
Linus Torvalds(torvalds@cs.helsinki.fi)
1996年8月6日星期二12:47:31 +0300(EET DST)
消息排序:[日期] [主题] [主题] [作者]
下一条消息:Bernd P. Ziller:"Re:在get_hash_table中哎呀"
上一条消息:Linus Torvalds:"Re:I/O请求订购"
1996年8月5日星期一,Peter P. Eiserloh写道:
我们需要明确线程的概念.太多人似乎将一个线程与一个进程混淆.以下讨论并未反映Linux的当前状态,而是试图保持高级别的讨论.
没有!
没有理由认为"线程"和"进程"是独立的实体.这就是它传统上的做法,但我个人认为这样做是一个很大的错误.这种方式的唯一理由是历史包袱.
线程和进程实际上只是一件事:"执行的上下文".试图人为地区分不同的案例只是自我限制.
"执行的背景",在此称为COE,只是该COE所有州的集团.该状态包括CPU状态(寄存器等),MMU状态(页面映射),权限状态(uid,gid)和各种"通信状态"(打开文件,信号处理程序等).传统上,"线程"和"进程"之间的区别主要在于线程具有CPU状态(可能还有其他一些最小状态),而所有其他上下文都来自进程.然而,这只是 划分COE总状态的一种方式,没有任何东西可以说这是正确的方法.将自己限制在那种形象上只是简单的愚蠢.
Linux对此的思考方式(以及我希望工作的方式)是没有"进程"或"线程"这样的东西.只有COE的全部(Linux称为"任务").不同的COE可以彼此共享其上下文的一部分,并且该共享的一个子集是传统的"线程"/"过程"设置,但是这应该被视为仅仅是一个子集(它是一个重要的子集,但重要性来自不是来自设计,而是来自标准:我们很想在Linux上运行符合标准的线程程序.
简而言之:不要围绕线程/流程思维方式进行设计.内核应该围绕COE思维方式设计,然后pthreads 库可以将有限的pthreads接口导出到想要使用这种方式查看COE的用户.
正如您认为COE与线程/流程相反时可能出现的一个例子:
你可以做一个外部的"cd"程序,这在UNIX和/或进程/线程中是传统上不可能的(愚蠢的例子,但想法是你可以拥有这些不仅限于传统UNIX的"模块")/threads setup).做一个:
克隆(CLONE_VM | CLONE_FS);
child:execve("external-cd");
/*"execve()"将取消关联VM,因此我们使用CLONE_VM的唯一原因是使克隆行为更快*/
你可以自然地做"vfork()"(它需要最小的内核支持,但这种支持完全符合CUA的思维方式):
克隆(CLONE_VM);
孩子:继续跑,最后execve()
妈妈:等待execve
你可以做外部"IO deamons":
克隆(CLONE_FILES);
child:打开文件描述符等
妈妈:用fd打开孩子和vv.
所有上述工作都是因为你没有依赖于线程/进程的思维方式.以Web服务器为例,其中CGI脚本是作为"执行线程"完成的.你不能用传统的线程做到这一点,因为传统的线程总是必须共享整个地址空间,所以你必须链接你想要在Web服务器本身做的所有事情(一个"线程"不能运行另一个可执行文件
作为一个问题的"执行的情况下"这一思想,而不是,你的任务现在可以选择执行外部程序(=分离从父地址空间)等,如果他们想,也可以例如与父母分享一切,除了为文件描述符(以便子"线程"可以打开大量文件,而父母不需要担心它们:当子"线程"退出时它们会自动关闭,并且它不会用掉父级中的fd) .
例如,可以考虑使用线程化的"inetd".你想要低开销的fork + exec,所以用Linux的方式你可以代替使用"fork()"来编写一个多线程的inetd,其中每个线程只用CLONE_VM创建(共享地址空间,但不共享文件)描述符等).然后孩子可以执行,如果它是一个外部服务(例如rlogind),或者它可能是内部inetd服务之一(echo,timeofday),在这种情况下,它只是做它的事情并退出.
你不能用"线程"/"进程"来做到这一点.
莱纳斯
以下是我从"守则项目 "的一篇文章中得到的内容.我想它清楚地解释了所需的一切.
线程是将工作负载拆分为单独的执行流的另一种机制.线程比进程重量轻.这意味着,它提供的灵活性低于完整的流程,但可以更快地启动,因为操作系统的设置较少.当程序由两个或多个线程组成时,所有线程共享一个内存空间.进程被赋予单独的地址空间.所有线程共享一个堆.但每个线程都有自己的堆栈.
线程和进程之间的区别?
进程是应用程序的执行实例,而线程是进程内的执行路径.此外,一个进程可以包含多个线程.重要的是要注意一个线程可以执行进程可以执行的任何操作.但由于进程可以包含多个线程,因此可以将线程视为"轻量级"进程.因此,线程和进程之间的本质区别是每个人用来完成的工作.线程用于小任务,而进程用于更"重量级"的任务 - 基本上是应用程序的执行.
线程和进程之间的另一个区别是同一进程中的线程共享相同的地址空间,而不同的进程则不共享.这允许线程读取和写入相同的数据结构和变量,并且还促进线程之间的通信.进程之间的通信(也称为IPC或进程间通信)非常困难且资源密集.
以下是线程和进程之间差异的摘要:
线程比进程更容易创建,因为它们不需要单独的地址空间.
多线程需要仔细编程,因为线程共享数据结构,一次只能由一个线程修改.与线程不同,进程不共享相同的地址空间.
线程被认为是轻量级的,因为它们使用的资源远少于进程.
流程彼此独立.线程,因为它们共享相同的地址空间是相互依赖的,所以必须小心谨慎,以便不同的线程不会相互踩踏.
这是另一种说明#2的方式.
进程可以包含多个线程.
线程在共享内存空间中运行,但进程在单独的内存空间中运行
线程是一个轻量级的过程,但一个过程是一个重量级的过程.
线程是进程的子类型.
从访问者的角度来看,基本上只有3个主要内容我想听,除了明显的事情,比如一个进程可以有多个线程:
线程共享相同的内存空间,这意味着线程可以从其他线程内存访问内存.流程通常不能.
资源.资源(内存,句柄,套接字等)在进程终止时释放,而不是线程终止.
安全.进程具有固定的安全令牌.另一方面,线程可以冒充不同的用户/令牌.
如果你想要更多,Scott Langham的回应几乎涵盖了一切.所有这些都是从操作系统的角度出发的.不同的语言可以实现不同的概念,如任务,轻量级线程等,但它们只是使用线程(Windows上的光纤)的方式.没有硬件和软件线程.有硬件和软件异常和中断,或用户模式和内核线程.
处理:
流程基本上是一个正在执行的程序。它是一个活动实体。一些操作系统使用术语“任务”来指代正在执行的程序。进程始终存储在主存储器中,也称为主存储器或随机存取存储器。因此,过程被称为活动实体。如果重新启动计算机,它将消失。多个进程可能与同一程序相关联。在多处理器系统上,可以并行执行多个进程。在单处理器系统上,尽管无法实现真正的并行性,但仍应用了一种进程调度算法,并且该处理器被调度为一次执行一个进程,从而产生并发错觉。示例:执行“计算器”程序的多个实例。每个实例都称为一个过程。
线:
线程是进程的子集。它被称为“轻量级进程”,因为它类似于真实进程,但在进程的上下文中执行并共享内核分配给进程的相同资源。通常,一个进程只有一个控制线程–一次执行一组机器指令。进程也可以由同时执行指令的多个执行线程组成。多控制线程可以利用多处理器系统上可能的真正并行性。在单处理器系统上,应用线程调度算法,并安排处理器一次运行每个线程。进程中运行的所有线程共享相同的地址空间,文件描述符,堆栈和其他与进程相关的属性。由于进程的线程共享相同的内存,
ref- https://practice.geeksforgeeks.org/problems/difference-between-process-and-thread
流程:执行中的程序称为流程
线程:线程是一个功能,它与程序的其他部分基于"一个与他人"的概念一起执行,因此线程是进程的一部分.
来自嵌入式世界,我想补充说,进程的概念只存在于具有MMU(内存管理单元)的"大"处理器(桌面CPU,ARM Cortex A-9)和支持使用MMU的操作系统中(比如Linux).对于小/旧处理器和微控制器以及小型RTOS操作系统(实时操作系统),例如freeRTOS,没有MMU支持,因此没有进程而只有线程.
线程可以访问彼此的内存,它们由OS以交错的方式进行调度,因此它们看起来并行运行(或者它们实际上是并行运行的多核).
另一方面,进程存在于由MMU提供和保护的虚拟内存的私有沙箱中.这很方便,因为它可以:
防止错误进程导致整个系统崩溃.
通过使其他进程数据不可见且无法访问来维护安全性.流程中的实际工作由一个或多个线程负责.
尝试从Linux内核的OS视图中回答
当程序启动到内存中时,它成为一个进程。进程具有其自己的地址空间,这意味着在内存中具有各种段,例如.text
用于存储已编译代码的段,.bss
用于存储未初始化的静态或全局变量等的段。
每个进程将具有自己的程序计数器和用户空间堆栈。
在内核内部,每个进程将具有自己的内核堆栈(出于安全性问题与用户空间堆栈分开)和一个命名为的结构,该结构task_struct
通常抽象为进程控制块,存储有关进程的所有信息,例如优先级,状态,(以及很多其他大块)。
一个进程可以有多个执行线程。
进入线程后,它们驻留在进程内部,并与创建线程时可以传递的其他资源(例如文件系统资源,共享挂起的信号,共享数据(变量和指令))一起共享父进程的地址空间。因此可以更快地进行上下文切换。
在内核内部,每个线程都有自己的内核堆栈以及task_struct
定义线程的结构。因此,内核将同一进程的线程视为不同的实体,并且它们本身是可调度的。同一进程中的线程共享一个称为线程组id(tgid
)的公共ID ,也有一个唯一的ID,称为进程ID(pid
)。
基本上,线程是进程的一部分,没有进程线程无法工作.
线程是轻量级的,而过程是重量级的.
进程之间的通信需要一些时间,而线程需要更少的时间
线程可以共享相同的内存区域,而进程可以分开存在.
对于那些更愿意通过可视化学习的人,这是我创建的一个方便使用的图表,用于解释进程和线程。
我使用了MSDN中的信息- 关于进程和线程
在用Python(解释语言)构建包含多线程的算法时,我很惊讶地发现与我之前构建的顺序算法相比,执行时间并没有改善。为了理解产生此结果的原因,我进行了一些阅读,并相信所学内容提供了一个有趣的上下文,从中可以更好地理解多线程与多进程之间的区别。
多核系统可能会行使多个执行线程,因此Python应该支持多线程。但是Python不是编译语言,而是解释语言1。这意味着必须对程序进行解释才能运行,并且解释程序在开始执行之前并不了解该程序。但是,它确实知道Python的规则,然后它动态地应用这些规则。那么,Python中的优化必须主要是解释器本身的优化,而不是要运行的代码。这与诸如C ++之类的编译语言相反,并且对Python中的多线程具有影响。具体来说,Python使用全局解释器锁来管理多线程。
另一方面,编译语言是编译好的。该程序被“完整地”处理,首先根据其句法定义对其进行解释,然后映射到与语言无关的中间表示形式,最后链接到可执行代码中。此过程可以高度优化代码,因为在编译时都可用。在创建可执行文件时可以定义各种程序交互和关系,并且可以做出关于优化的可靠决策。
在现代环境中,Python的解释器必须允许多线程,而且这必须既安全又高效。这就是解释语言与编译语言之间的差异进入画面的地方。解释器不得干扰来自不同线程的内部共享数据,同时必须优化处理器在计算中的使用。
如前几篇文章所述,进程和线程都是独立的顺序执行,主要区别在于,进程的多个线程之间共享内存,而进程隔离其内存空间。
在Python中,全局解释器锁保护数据免受不同线程的同时访问。它要求在任何Python程序中任何时候都只能执行一个线程。另一方面,可以运行多个进程,因为每个进程的内存与任何其他进程都是隔离的,并且进程可以在多个内核上运行。
1 Donald Knuth在“计算机编程艺术:基础算法”中很好地解释了解释性例程。
there,作为一名正在学习OS课程的本科生,我已经仔细阅读了几乎所有答案,但是我无法完全理解这两个概念。我的意思是大多数人都从某些OS书籍中读到了差异,即线程能够访问事务单元中的全局变量,因为它们利用了进程的地址空间。但是,新的问题提出了为什么要有进程,众所周知,我们已经知道线程相对于进程而言是更轻量级的。让我们看一下下面的示例,其中使用了从先前答案之一摘录的图像,
我们有3个线程同时处理一个单词文档,例如Libre Office。第一个通过下划线强调单词是否拼写来进行拼写检查。第二个接收并打印键盘上的字母。最后一个确实在每一次短时间内都保存了文档,以防万一出了问题而丢失了工作文档。在这种情况下,这3个线程不能是3个进程,因为它们共享一个公共内存,该内存是其进程的地址空间,因此所有人都可以访问正在编辑的文档。因此,道路是“文件”一词,还有两个推土机,它们是线程,尽管图像中缺少其中之一。