进程/线程/协程的区别
1 基本概念
进程(Process)
进程是应用程序的启动实例,进程拥有代码和打开的文件资源、数据资源、独立的内存空间。
线程(Lightweight Process,LWP)
线程从属于进程,是程序的实际执行者,一个进程至少包含一个主线程,也可以有更多的子线程,线程拥有自己的栈空间。
对操作系统而言,线程是最小的执行单元,进程是最小的资源管理单元。无论是进程还是线程,都是由操作系统所管理的。协程(Coroutines)
协程是一种比线程更加轻量级的存在,正如一个进程可以拥有多个线程一样,一个线程可以拥有多个协程。协程不是被操作系统内核所管理的,而是完全由程序所控制,也就是在用户态执行。这样带来的好处是性能大幅度的提升,因为不会像线程切换那样消耗资源。
进程、线程、协程的对比:
(1)协程既不是进程也不是线程,协程仅仅是一个特殊的函数,协程它进程和进程不是一个维度的。
(2)一个进程可以包含多个线程,一个线程可以包含多个协程。
(3)一个线程内的多个协程虽然可以切换,但是多个协程是串行执行的,只能在一个线程内运行,没法利用CPU多核能力。
(4)协程与进程、线程一样,切换是存在上下文切换问题的。
上下文切换对比:
(1)进程的切换者是操作系统,切换时机是根据操作系统自己的切换策略,用户是无感知的。进程的切换内容包括页全局目录、内核栈、硬件上下文,切换内容保存在内存中。进程切换过程是由“用户态到内核态到用户态”的方式,切换效率低。
(2)线程的切换者是操作系统,切换时机是根据操作系统自己的切换策略,用户是无感知的。线程的切换内容包括内核栈和硬件上下文,线程切换内容保存在内核栈中.线程切换过程是由“用户态到内核态到用户态”,切换效率中等。因为线程的调度是在内核态运行的,而线程中的代码是在用户态运行,因此线程切换会导致用户态与内核态的切换
(4)协程的切换者是用户(编程者或应用程序),切换时机是用户自己的程序所决定的。协程的切换内容是硬件上下文,切换内存保存在用户自己的变量(用户栈或堆)中。协程的切换过程只有用户态,即没有陷入内核态,因此切换效率高。
1.1 进程调度
MAX_RT_PRIO = 100
普通进程,SCHED_NORMAL调度策略 0~MAX_RT_PRIO-1, 即0~99
实时进程,SCHED_FIFO,或SCHED_PR调度策略 MAX_RT_PRIO~MAX_RT_PRIO+40, 即 100~140
linux根据进程优先级来进行调度,任何时候,实时进程的优先级都高于普通进程,实时进程只会被更高级的实时进程抢占,同级实时进程之间是按照FIFO(一次机会做完)或者RR(多次轮转)规则调度的。
实时进程
不同与普通进程,系统调度时,实时优先级高的进程总是先于优先级低的进程执行。直到实时优先级高的实时进程无法执行。实时进程总是被认为处于活动状态。如果有数个 优先级相同的实时进程,那么系统就会按照进程出现在队列上的顺序选择进程。不同调度策略的实时进程只有在相同优先级时才有可比性:
1、对于FIFO的进程,意味着只有当前进程执行完毕才会轮到其他进程执行。由此可见相当霸道。
2、对于RR的进程。一旦时间片消耗完毕,则会将该进程置于队列的末尾,然后运行其他相同优先级的进程,如果没有其他相同优先级的进程,则该进程会继续执行。
总而言之,对于实时进程,高优先级的进程就是大爷。它执行到没法执行了,才轮到低优先级的进程执行。等级制度相当森严啊。
普通进程
Linux对普通的进程,根据动态优先级进行调度。而动态优先级是由静态优先级(static_prio)调整而来。Linux下,静态优先级是用户不可见的,隐藏在内核中。而内核提供给用户一个可以影响静态优先级的接口,那就是nice值,两者关系如下:
static_prio=MAX_RT_PRIO +nice+ 20
nice值的范围是-20至19,因而静态优先级范围在100至139之间。nice数值越大就使得static_prio越大,最终进程优先级就越低。
动态优先级:
dynamic_prio = max (100, min(static_prio - bonus + 5, 139)),
奖励(bonus)根据进程的平均睡眠时间计算所得,取值范围为0至10。
而进程的时间片就是完全依赖static_prio 定制的,见下图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JgfYGcsV-1663468431680)(3E433F7A7AB14A00ADD3693BBC01B760)]操作系统在选取运行进程的时候按照最小的vruntime来的,虚拟时间的计算公式为虚拟运行时间 vruntime += 实际运行时间 delta_exec * NICE_0_LOAD/ 权重,其中权重就是优先级。这就是说,同样的实际运行时间,给高优先级的算少了,低优先级的算多了,但是当选取下一个运行进程的时候,还是按照最小的 vruntime 来的,这样高优先级的获得的实际运行时间自然就多了。
参考链接
1.2 孤儿进程和僵尸进程
孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。
问题及危害:unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到。这种机制就是: 在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息(包括进程号the process ID,退出状态the termination status of the process,运行时间the amount of CPU time taken by the process等)。直到父进程通过wait / waitpid来取时才释放。 但这样就导致了问题,如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程. 此即为僵尸进程的危害,应当避免。
参考链接
1.3 进程间的通信方式
- 管道
管道分为匿名管道和命名管道,匿名管道由pipe系统调用创建。创建后会有两个文件句柄,一个用于读,一个用于写。匿名管道一般用于父子进程间的通信,管道是单向通信的,要实现进程之间的双向通信需要创建两个管道。命名管道由mkfifo创建,命名管道就是FIFO,管道是先进先出的通讯方式。FIFO是一种先进先出的队列。它类似于一个管道,只允许数据的单向流动。其与匿名管道的一个重要区别是它提供了一个文件路径名与之关联,任何进程只要能访问该文件就能实现进程间的相互通信。容量有限,速度慢。 - 消息队列
消息队列是消息的连接表,存放在内核中并由消息队列标识符标识这种通信机制传递的数据具有某种结构,而不是简单的字节流。消息队列是用于两个进程之间的通讯,首先在一个进程中创建一个消息队列,然后再往消息队列中写数据,而另一个进程则从那个消息队列中取数据。需要注意的是,消息队列是用创建文件的方式建立的,如果一个进程向某个消息队列中写入了数据之后,另一个进程并没有取出数据,即使向消息队列中写数据的进程已经结束,保存在消息队列中的数据并没有消失。 - 信号量
信号量不能传递复杂消息,只能用来同步 - 共享内存
只要首先创建一个共享内存区,两个进程只要按照进程A用户空间-共享内存-进程B用户空间的步骤就可以对共享内存区中的数据进行读写。
其中共享内存的效率最高,原因是共享内存的数据拷贝只有两次,即进程A的内存空间到共享内存,共享内存到进程B的内存空间。管道/消息队列的效率较低,原因是数据拷贝有四次。以消息队列为例,首先是进程A用户内存空间数据拷贝到A进程内核缓冲区,内核缓冲区数据拷贝到消息队列,进程B需要将消息队列数据拷贝到B进程内核缓冲区,最后将B进程内核缓冲区的数据拷贝到进程B的用户内存空间。 - socket套接字
套接字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
1.4 进程状态图
进程/线程/协程的区别相关推荐
- linux进程线程协程的区别,进程和线程、协程的区别
现在多进程多线程已经是老生常谈了,协程也在最近几年流行起来.python中也有协程库,tornado中也用了gevent封装好的协程.本文主要介绍进程.线程和协程三者之间的区别. 一.概念 1.进程 ...
- Linux的进程/线程/协程系列4:进程知识深入总结:上篇
Linux的进程/线程/协程系列4:进程/线程相关知识总结 前言 本篇摘要: 1. 进程基础知识 1.1 串行/并行与并发 1.2 临界资源与共享资源 1.3 同步/异步与互斥 1.4 进程控制原语 ...
- linux的进程/线程/协程系列5:协程的发展复兴与实现现状
协程的发展复兴与实现现状 前言 本篇摘要: 1. 协同制的发展史 1.1 协同工作制的提出 1.2 自顶向下,无需协同 1.3 协同式思想的应用 2. 协程的复兴 2.1 高并发带来的问题 2.2 制 ...
- linux的进程/线程/协程系列3:查看linux内核源码——vim+ctags/find+grep
linux的进程/线程/协程系列3:查看linux内核源码--vim+ctags/find+grep 前言 摘要: 1. 下载linux内核源码 2. 打标签方法:vim+ctags 2.1 安装vi ...
- linux的进程/线程/协程系列1:进程到协程的演化
linux的进程/线程/协程系列1:进程到协程的演化 前言 摘要: 1. 一些历史:批处理时代 2. 现代操作系统启动过程 3. 进程(process)的出现 4. 线程(thread)与线程池 5. ...
- 进程 线程 协程 各自的概念以及三者的对比分析
文章目录 1 进程 2 线程 3 进程和线程的区别和联系 3.1 区别 3.2 联系 4 举例说明进程和线程的区别 5 进程/线程之间的亲缘性 6 协程 线程(执行一个函数)和协程的区别和联系 协程和 ...
- 简要说明__python3中的进程/线程/协程
多任务可以充分利用系统资源,极大提升程序运行效率,多任务的实现往往与 多线程,多进程,多协程有关 稳定性: 进程 > 线程 > 协程 系统资源占用量:进程 > 线程 > 协程 ...
- Python之进程+线程+协程(异步、selectors模块、阻塞、非阻塞IO)
文章目录 一.IO多路复用 二.selectors模块 本篇文字是关于IO多路复用的更深入一步的总结,上一篇 Python之进程+线程+协程(事件驱动模型.IO多路复用.select与epoll)对I ...
- python进程线程协程区别_Python3多线程与协程
python中的多线程非常的常用,之前一直糊里糊涂地使用,没有一些系统性的概念,记录一下~ 0x001 多线程的优势:可将长时间占用的程序放到后台 可能会加速程序执行速度 能够实现一些类似同步执行的效 ...
最新文章
- 小米快传文件服务器怎么用,手机中的小米快传怎么用?小米快传的详细使用教程...
- 《数据结构》第01章在线测试
- badboy测试工具下载
- 什么是Vue?Vue的工作原理是什么?
- Sublime Text 关闭自动更新
- 【Java】Float计算不准确
- Angular自学笔记(?)DI提供者
- JMetro版本11.5.11和8.5.11发布
- 帮助企业降本增效,提高IT运营效率的六种方法
- Java图片压缩 BufferedImage Linux 下代码阻塞不工作
- git 应用 branch指针和HEAD指针
- 教你如何防止网站被挂马!
- Linux内核——定时器和时间管理
- 计算机中丢失xvidcore.dll,出现xvidcore.dll not found 问题的解决方法
- 经纬度在线查询 地名 批量 查询经纬度 经纬度 批量 查询地名
- Nature|人类肠道细菌对治疗药物的生物累积
- 【沃顿商学院学习笔记】宏观经济学——09欧元区Euro Zone
- 205. Isomorphic Strings
- 【OpenPCDet】稀疏卷积SPConv-v1.2代码解读(5)
- 空洞卷积原理详解及其pytorch代码实现