进程(同步) 线程 超线程 以及上下文等一些相关OS基础

线程与进程

进程是资源共享的最小单位,线程是内存调度的最小单位。

进程:可以理解成一个程序,是占有一定Cpu资源、它是系统进行资源分配和调度的一个独立单位,重点在系统调度和单独的单位,也就是说进程是可以独 立运行的一段程序。比如说,运行Chrome浏览器,那这个浏览器程序,就是一个进程。
线程:一个进程至少有一个线程。线程是CPU的实际调度和分派的基本单位,他是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源。比如说Chrome浏览器,它就有很多的线程,每一个标签就是一个新的线程,这些线程共享占用着进程所占有的系统资源。

两者系统开销:

进程在创建和销毁的时候,系统都要为之分配或者回收资源,如内存空间、i/o设备等。
在进行进程切换的时候,涉及到整个当前进程的CPU环境的保存以及新被调用运行的进程CPU环境的设置。
而线程的切换只需要保存和设置少量寄存器的内容,并不涉及存储器管理方面的操作。
由于同一进程中的多个线程具有相同的地址空间,所以他们之间的同步和通信的实现变得相对容易。

超线程

超线程:假如说我有个单核的CPU,我要是想要运行一个多线程的程序,通常情况下,只能是由Cpu在线程之间来回调度,但是当我开启了超线程,我可以在一个线程执行整数指令集的时候,而恰好在这个时候,另一个线程执行浮点指令集,而这两个指令集分数与整数指令单元和浮点指令单元来执行。那么我就可以同时执行这两个线程,这就叫超线程。而且实际上,是有大量资源被闲置着的。超线程技术允许两个线程同时不冲突地使用CPU中的资源。
指令单元闲置,可以通过超线程的技术来达到提高利用率。这叫做硬件多线程技术。

下面详细介绍一次进程(进程同步)和线程(用户级和内核级线程)相关知识

进程

先简单说一下进程的几种常见状态和转换
在这里插入图片描述

进程同步

进程同步的目的是:对多个相关的进程在执行次序上进行协调,是并发执行的诸个进程之间有效的共享资源和相互合作

进程同步的方式

  1. 互斥量 Synchronized/Lock:采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问
  2. 信号量 Semphare:本身是一个计数器,使用P,V两个操作来实现计数的减与加,当计数不大于0时,则进程进入睡眠状态,它用于为多个进程提供共享数据对象的访问。(信号量也是进程间通信(IPC)的一种方式)
  3. 事件(信号),Wait/Notify:通过通知操作的方式来保持多线程同步,还可以方便的实现多线程优先级的比较操作

进程同步遵循的原则

  1. 空闲让进:无进程进入临界区时,相应的临界资源处于空闲状态,因而允许一个请求进入临界区的进程立即进入自己的临界区。
  2. 忙则等待:当已有进程进入自己的临界区时,其它试图进入临界区的进程必须等待保证对临界区的互斥访问
  3. 有限等待:对要求访问临界资源的进程,应保证进程能在有限时间进入临界区,避免“饥饿”
  4. 让权等待:当进程不能进入自己的临界区时,应该释放处理机,以免陷入忙等状态

线程

用户级线程和内核线程

用户级线程(user level thread)ULT

该类线程由应用程序管理,内核不知道该线程的存在。

app(应用程序)启动之后,OS分配给该程序一个进程号以及对应的内存空间等资源。
APP就先在一个线程中运行,该线程就是主线程,其他运行时刻,可以调用线程库中的函数创建一个新的运行在同一个进程中的线程。

优点:

  1. 不用进入内核空间,所以高效、切换开销很小(无需陷入内核);
  2. 线程的调度不需要内核直接参与,控制简单
  3. 允许每个线程定制自己的调度算法,线程管理比较灵活
    线程能够利用的表空间和堆栈空间比内核级线程多。

缺点:
并发效率不高,同一进程中只能同时有一个线程在运行,除非这个线程放弃CPU,单独进程内部,没有时钟中断,所以不能用轮转调度;
如果有一个线程使用了系统调用而阻塞,那么整个进程都会被挂起。
在这里插入图片描述

扫描二维码关注公众号,回复: 5721051 查看本文章

内核级线程(kernel level thread)KLT

这类线程管理的所有工作由内核完成,应用程序没有进行线程管理的代码,只能调用内核线程的接口。

内核维护进程及其内部的每个线程,调度也由内核基于线程架构完成。

优点:内核可以将不同线程更好地分配到不同的CPU,以实现真正的并行计算,当一个线程阻塞时,内核根据选择,可以运行同一个进程或其他进程

缺点:由内核进行调度
即使CPU在同一个进程的多个线程之间切换。也须要陷入内核,因此其速度和效率不如用户级线程。(代价较高)

用户级、核心级线程相结合的多线程实现

线程创建完全在用户空间中完成,线程的调度和同步也在应用程序中进行. 一个应用程序中的多个用户级线程被映射到一些(小于或等于用户级线程的数目)内核级线程上。

根据映射的关系,又分为多对一混合线程模型和多对多线程模型。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
课本上的三种线程形式如下图:
在这里插入图片描述

用户级线程和内核级线程的区别

  1. 内核是否可感知: 内核支持线程是OS内核可感知的,而用户级线程是OS内核不可感知的
  2. 线程的管理是否需要内核支持: 用户级线程的创建、撤消和调度不需要OS内核的支持,是在语言(如Java)这一级处理的;而内核支持线程的创建、撤消和调度都需OS内核提供支持,而且与进程的创建、撤消和调度大体是相同的。
  3. 执行系统调用指令时线程是否中断: 用户级线程执行系统调用指令时将导致其所属进程被中断,而内核支持线程执行系统调用指令时,只导致该线程被中断。
  4. CPU调度的单位: 在只有用户级线程的系统内,CPU调度还是以进程为单位,处于运行状态的进程中的多个线程,由用户程序控制线程的轮换运行;在有内核支持线程的系统内,CPU调度则以线程为单位,由OS的线程调度程序负责线程的调度。
  5. 线程的程序实体: 用户级线程的程序实体是运行在用户态下的程序,而内核支持线程的程序实体则是可以运行在任何状态下的程序。

一些专有名词

在这里插入图片描述

内核:本质上是一个软件–控制计算机的硬件资源,并提供上层应用程序运行的环境;

内核空间:供操作系统内核使用

**用户空间:**供各个进程使用,并且所有进程共享

**内核态:**操作系统内核所运行的模式,运行在该模式的代码,可以无限制地对系统存储、外部设备进行访问。运行于内核空间

**用户态:**以处理器的最低特权级别进行调用,运行于用户空间,即上层应用程序的活动空间。

陷入内核:当一个任务(进程)执行系统调用或触发异常而中断时会陷入内核代码中执行时,我们就称进程处于内核运行态(或简称为内核态)

“系统调用”: 内核为上层调用提供的接口

上下文context:上下文简单说来就是一个环境,相对于进程而言,就是进程执行时的环境。具体来说就是各个变量和数据,包括所有的寄存器变量、进程打开的文件、内存信息等。

用户态->内核态的三种方式:

  1. 系统调用
  2. 异常:缺页异常等
  3. 外围设备中断:打印机设备故障

处理器总会处于以下状态中的一种:
1、内核态,运行于进程上下文,内核代表进程运行于内核空间;

2、内核态,运行于中断上下文,内核代表硬件运行于内核空间;

3、用户态,运行于用户空间。

内核可以处于两种上下文:进程上下文和中断上下文。在系统调用之后,用户应用程序进入内核空间,此后**内核空间针对用户空间相应进程的代表就运行于进程上下文**。异步发生的中断会引发中断处理程序被调用,**中断处理程序就运行于中断上下文**。
**中断上下文和进程上下文不可能同时发生。**

进程上下文:进程在执行的时候,CPU中所有寄存器的值、进程的状态以及堆栈上的内容等状态,在内核需要切换到另一个进程的时候都需要保存,以便再次执行当前进程的时候,快速恢复切换前的状态。这些状态信息统称当前进程的进程上下文。

“中断上下文”:其实也可以看作就是硬件传递过来的这些参数和内核需要保存的一些其他环境(主要是当前被中断的进程环境)。

简单描述:当一个进程在执行时,CPU的所有寄存器中的值、进程的状态以及堆栈中的内容被称为该进程的上下文。

一个进程的上下文可以分为三个部分:用户级上下文、寄存器上下文以及系统级上下文
在这里插入图片描述
上下文切换: 当发生进程调度时,进行进程切换就是上下文切换(context switch).

Linux内核态和用户态通信的方法

procfs
netlink(常用)
syscall
IOCTL
详见 https://blog.csdn.net/wuruixn/article/details/24960935

部分转自:https://blog.csdn.net/ChaunceyChen/article/details/86663463
https://blog.csdn.net/benjamin721/article/details/51316596

猜你喜欢

转载自blog.csdn.net/mulinsen77/article/details/88366064