进程、线程、协程相关知识积累

news/2024/10/23 9:38:47/

1.进程、线程、协程的区别

(1)进程是程序一次动态执行的过程,是程序运行的基本单位。操作系统会以进程为单位,分配系统资源(CPU时间片、内存等资源),进程是资源分配的最小单位。

进程占据独立的内存,所以上下文进程间的切换开销比较大。进程之间可以通过管道、信号量、消息队列、、套接字、共享内存进行通信。
(2)线程从属于进程,是程序的实际执行者。一个进程至少包含一个主线程,也可以有更多的子线程。
多个线程共享所属进程的资源(在jvm中包括堆、方法区),同时线程也拥有自己的专属资源(虚拟机栈、本地方法栈、程序计数器)。
线程间通信主要通过共享内存,上下文切换成本比进程低。
(3)协程既不是进程也不是线程,协程仅仅是一个特殊的函数,一个线程可以包括多个协程。
协程的上下文切换不是由操作系统管理的,而是由程序控制的,所以不需要像线程进行多次的用户态、内核态切换。

2.进程切换步骤

(1)切换页目录以使用新的地址空间
(2)切换内核栈和硬件上下文

所以在切换进程时,一定会有两个问题:

新的进程需要新的内存空间,将寄存器中的内容切换出来是最显著的性能消耗。
上下文的切换会扰乱处理器的缓存机制。一旦切换上下文,处理器中所有已经缓存的内存在址在一瞬间全部作废,
已缓存的页表被全部刷新,导致内存访问在一段时间内相当低效,程序运行也会变慢甚至出现卡顿。

3.什么是系统态、用户态?(线程什么时候会切换到内核态)

由于用户态不能直接使用系统资源,如CPU、内存、I/O等,内核提供了一组通用的访问接口,这些接口叫做系统调用,系统调用可以使程序从用户态到内核态进行切换。

除了系统调用这种自发的切换,异常和外围设备中断也会发生状态改变。异常会使当前运行进程切换到处理此异常的内核相关程序中,也就转到了内核态。

当外围设备完成用户请求的操作后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条即将要执行的指令转而去执行与中断信号对应的处理程序,如果先前执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了由用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。

4.线程模型(1:1 1:N N:M)

1:1 线程模型
1:1 模型,即每一个用户线程都对应一个内核线程,每个线程的创建、调度、销毁都需要内核的支持,每次线程的创建、切换都会设计用户状态/内核状态的切换,性能开销比较大,并且单个进程能够创建的LWP的数量是有限的,但能够充分里用多核的优势

N:1 线程模型
N:1模型,即所有的用户线程都会对应到一个内核线程中,该模型可以在用户空间完成线程的创建、调度、销毁,不需要内核的支持,同样也就不涉及用户状态/内核状态的切换,线程的操作较快且消耗较低,并且线程数量不受操作系统的限制,但不能发挥多核的优势,只能在一个核中分时复用,并且由于内核不能感知用户态的线程,在某一线程被阻塞时,会导致整个所属进程阻塞

N:M 线程模型
N:M 模型是基于以上两种模型的一种混合实现,多个用户线程对应于多个内核线程,即解决了1:1模型中性能开销及线程数量的问题,也解决了N:1模型中阻塞问题,同时也能充分利用CPU的多核优势,这也是大部分协程实现的基础

Java在1.2之前基于用户线程实现(N:1线程模型),在1.2之后windows及linux平台下采用1:1线程模型(这也是java线程切换需要切换系统态的原因),在solaris平台使用1:1或N:M线程模型实现(可配置)

5.用户态切换到系统态为什么费时间?

(1)下面是从用户态切换到内核态的主要步骤:

用户程序发起系统调用
用户程序使用系统调用库中提供的函数,如read、write等,向操作系统发起请求。

中断触发
当用户程序调用系统调用库中的函数时,CPU会发出一个软中断(软件中断),即通过在中断向量表中查找相应的系统调用处理程序地址并跳转至其执行。该中断会把当前进程挂起,将控制权转交给内核。

执行内核代码
一旦CPU进入内核空间,就可以执行内核代码了。此时,CPU可以访问所有的系统资源,包括设备驱动程序、文件系统、网络协议栈等。

执行系统调用
内核开始执行用户程序请求的系统调用,并按照用户程序提供的参数进行操作。例如,如果用户程序请求读取文件,内核会根据用户程序提供的参数,在文件系统中查找文件并读取数据。

返回用户程序
当内核完成请求的操作后,它将结果返回给用户程序,并将控制权返回给用户程序。此时,CPU重新切换到用户态。
 


http://www.ppmy.cn/news/1126693.html

相关文章

Java Matcher对象中 find() 与 matches() 的区别

find():字符串某个部分匹配上正则表达式就会返回true matches():整个字符串都匹配上正则表达式才返回true,否则false 参考:Java Matcher对象中find()与matches()的区别 参考:Pattern隐藏了哪些Java8追加的新功能 参考&…

k8s 自动扩缩容HPA原理及adapter配置详解

大家好,我是蓝胖子,都知道,k8s拥有自动扩缩容机制HPA,我们能够通过配置针对不同的扩缩容场景进行自动扩缩容,往往初学者在面对其中繁多配置的时候会学了又忘记,今天我将会以一种不同的视角,结合…

《安富莱嵌入式周报》第323期:NASA开源二代星球探索小车, Matlab2023b,蓝牙照明标准NLC, Xilinx发布电机套件,Clang V17发布

周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版: https://www.bilibili.com/video/BV1vp4y1F7qD 《安富莱嵌入式周报》第323期:NASA开源…

字符编码个人理解

总结:ASCII码只占一个字节,不包含汉字;GBK汉字国标扩展码,就是所谓的中国码,兼容ASCII码,汉字包含两个字节;Unicode万国码,兼容所有国家文字;UTF-32,所有字符都占4个字节…

记一次 .NET 某拍摄监控软件 卡死分析

一:背景 1. 讲故事 今天本来想写一篇 非托管泄露 的生产事故分析,但想着昨天就上了一篇非托管文章,连着写也没什么意思,换个口味吧,刚好前些天有位朋友也找到我,说他们的拍摄监控软件卡死了,让…

L1-033 出生年 c++解法

一、题目再现 以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才遇到4个数字都不相同的年份。”也就是说,直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求,自动填充“我出生于y年,直到x岁才遇到n个…

Zynq-Linux移植学习笔记之63- linux内核崩溃的重启

1、背景介绍 在运行linux应用程序的时候,有时会遇到内核崩溃异常的情况,此时串口中会打印出内核崩溃时的堆栈情况,如下: 当出现这个情况后串口就死了,应用也停了,此时无法进行恢复。 之前写过可通过板子w…

C#之性能优化

一、垃圾回收 1.避免不必要的对象创建 ①避免循环创建对象 如果对象并不会随每次循环而改变状态,那么在循环中反复创建对象将带来性能损耗。高效的做法是将对象提到循环外面创建。 ②在需要逻辑分支中创建对象 如果对象只在某些逻辑分支中才被用到,…