揭秘计算机内部奥秘:从CPU到操作系统,深入探索进程与线程的工作原理

 📃个人主页island1314

⛺️  欢迎关注:👍点赞 👂🏽留言 😍收藏  💞 💞 💞


引言

计算的需求在人类的历史中是广泛存在的,发展大体经历了从一般计算工具到机械计算机到目前的电子计算机的发展历程。人类对计算的需求,驱动我们不断的发明、改善计算机。目前这个时代是“电子计算机”的时代,发展的潮流是:更快速、更稳定、更微型。计算机的以后将如何发展,期待大家的努力。

 1.  🌈冯诺依曼体系

🌈现代的计算机 , 大多遵守 冯诺依曼体系结构,如下图所示:

存储器:

  • 内存(咱们平时说的内存、运行内存):存储空间小,访问速度快,成本高,掉电后数据丢失
  • 外存(硬盘,软盘,光盘,U盘):存储空间大,访问速度慢,成本低,掉电后数据保留

输入设备: 用户给计算机发号施令的设备,如鼠标、键盘等

输出设备: 计算机给用户汇报结果的设备,如显示屏等

2. 内存和硬盘区别

  • 硬盘比较大,内存比较小(这里指的不是物理尺寸,是存储空间容量),针对存储空间–硬盘 > 内存 >> CPU
  • 硬盘读写速度比较慢,内存读写速度比较快(几千倍甚至上万倍),针对数据访问速度–CPU >> 内存 > 硬盘
  • 针对成本–CPU>内存>硬盘

3. CPU

🌈CPU(Center Process Unit )全称是中央处理器,由ALU + CU + 寄存器 + 时钟组成,一般电子计算机中的cpu依靠背后的一个时钟来进行周期驱动。

衡量CPU的重要指标(当然远远不止这两个啦):

  1. 核心数 – 通过在编程中引入一些特定的方式,来把多个cpu核心利用起来(并发编程)。
  2. 主频 ----- 粗略来讲,就是时钟的震荡的每秒次数,可以近似的看作每秒执行的指令数。

这两个值越高说明CPU越好,因此我们也可以通过这些来提升CPU 的性能

  1.  把门电路做的足够小,(但是以现在的水平当门电路过小时即达到微粒水平,平时我门所熟知的物理规律便失效了,进入量子力学范畴,目前不可控)
  2. 把CPU做的足够大(但是这与工艺水平有很大关系,CPU做的越大制作过程中间出现错误的可能性就越高,CPU的废品率就越高,会提高成本)。所以厂家们想出来了 多核心的CPU,即一个CPU板上放多个CPU。这也就导致了并发编程的由来。后来又演化出 超线程技术,即把一个CPU当成两个也就是逻辑处理器,我们俗称大小核。现在的CPU都是多核加超线程技术加持下的产物。

这里我们就不过多详细讲解,就做个大概了解就行

 4. 操作系统(Operating System)

操作系统是一组做计算机资源管理的软件的统称。

操作系统 = 内核+配套的应用程序,其中内核是操作系统最核心的功能,系统的驱动程序都是在系统内核中执行的

目前常见的操作系统有:Windows系列、Unix系列、Linux系列、OSX系列、Android系列、iOS系列、鸿蒙等。

内核的功能就是

  1. 管理硬件设备:硬件厂商会提供相应的驱动程序,操作系统通过驱动程序间接操作硬件设备
  2. 给软件提供稳定的运行环境,现在的操作系统上一般会同时运行很多程序,操作系统会确保当某个程序出问题了,不会影响别的程序执行(例如,你在写代码正在听网易云音乐,当你的代码出bug了,你的网易云音乐不会停止)

操作系统由两个基本功能:

  1. 防止硬件被应用程序滥用;
  2. 向应用程序提供简单一致的机制来控制复杂而又通常大相径庭的低级硬件设备。

操作系统通过抽象封装来管理各种硬件,并给应用程序提供API(接口)和 稳定的运行环境

5. 进程📚

5.1 🥑进程的概念

每个应用程序运行于现代操作系统之上时,操作系统会提供一种抽象,好像系统上只有这个程序在运行,所有的硬件资源都被这个程序在使用。这种假象是通过抽象了一个进程的概念来完成的,进程可以说是计算机科学中最重要和最成功的概念之一。


进程是操作系统对一个正在运行的程序的一种抽象,换言之,可以把进程看做程序的一次运行过程;同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。

5.2 🍉进程控制块(PCB)

进程是操作系统对于程序运行过程的描述,而这个描述学名叫作 进程控制块-PCB,它是操作系统管理以及调度程序运行的唯一实体,用来描述进程的属性。

在系统中一般会采取双向链表这样的形式来管理PCB,创建新的进程就是创建 PCB 然后把 PCB 插入到链表中,销毁进程,就是把 PCB 从 链表上删除并是否,展示进程列表,就相当于遍历链表的每个节点。

操作系统利用类/结构体的方式对进程的抽象表示,即名称为PCB的类/结构体。它非常庞大,有上百个属性。注:在Linux 中 PCB 我们一般叫作 task_struct

  1. pid :进程的身份标识符,通过简单的不重复整数区分,是唯一的,pid一般来说是32位整数;用pid可对进程操作区分。
  2. 内存指针 :表述进程能使用那些内存,表述进程使用内存资源详细情况。
  3. 文件描述符表 :操作系统对硬盘设备进行封装,操作系统统一进行抽象都是按照文件方式操作的。
  4. 进程状态 :表示某个进程是否能去CPU执行,有就绪状态,阻塞状态等。
  5. 进程优先级 :进程调度时的依据
  6. 记账信息 :针对每个进程占据多少CPU时间进行统计,会根据这个统计结果进行调整调度的策略;确保每个进程都可以使用到CPU。
  7. 上下文 :支撑进程调度的重要属性,相当于游戏中的存档和读档。

注:后面四点是用来完成 进程的调度(下文我们会单独介绍)

5.3 🥝进程管理

1.先描述:先利用类或结构体把进程中的实体属性列出来,即PCB。

2.再组织:通过一定的数据结构(链表)把这些结构、对象串在一起。

  • 在Linux中,使用链表这样的数据结构把若干个task_struct给串起来;当我们看到任务管理器的这些进程时,意味着系统内部在遍历链表,并且打印每个节点的相关信息;如果运行一个新的程序,系统中就会多一个进程,多的进程就需要构造出一个新的pcb并且添加到链表上;如果某个运行中的程序退出了,就需要把对应进程的pcb从链表中删除并且销毁对应的pcb资源。

内存管理:每个进程的内存彼此独立,互不干扰,通常情况下,进程A不能直接访问进程B的内存(系统稳定性)

5.4 🍋‍🟩进程调度

🍊早期的操作系统是一个 “单任务操作系统”,同一时刻只有一个进程能运行,然后要运行下一个进程,就会退出上一个(此时就不用考虑调度)

💢 而现在单任务已经满足不了我们的要求,太不方便了,因此计算机同时存在多个要执行的进程,CPU的每个核心可以执行一个进程(也就是执行里面的指令),但是一台机器CPU拥有的核心数量有限,但是却要执行几乎上百个进程,怎么办?

举个例子🌰:

就比如演个话剧,很多演员需要上去演,但是为了方便和好看,那么就会采用轮流上去演的方式,每个演员腌一会就下了,腾出地方,给其他演员去演。

进程调度解决了以上问题:分时复用,然后我们再来了解两个概念

  • 并发:多个进程在多个 CPU 核心上执行
  • 并行:单个CPU上采用快速轮转调度的方式执行多个进程

🔥 上述 并发 和 并行 都是处于应用程序这一层,感知不到,都是在系统内部来完成调度的。我们一般也不会具体去区分 并发 和 并行,从编程角度来说,底层是并发还是并行对代码豆没啥影响,平时也就统一 使用 并发 来代指 并行 和 并发,并发编程

因此由上面我们就可以 知道一个系统中可有这么多进程,也就是 并发编程 的效果。

下面这些属性,就是用于支持并发执行这个调度过程

(1)进程状态,包括以下5个

  • 新建状态:当一个进程被创建,但是未分配内存资源,此时这个进程就处于新建状态;
  • 就绪状态:可以随时被调度到CPU上执行指令的;
  • 运行状态:CPU正在执行某个进程的指令,这个进程就处于运行状态;
  • 阻塞状态:无法被调度到CPU上进行执行(因为要进行其他操作,例如写代码时使用Scanner等待用户输入,如果不去输入,程序会一直卡在这);
  • 终止状态:表示该进程完成了它的执行,与此同时该进程占用的系统资源也被回收

(2)进程优先级:进程调度时,有的进程先执行,有的进程后执行,这就是优先级

(3)进程上下文:分时复用,一个进程执行一段时间,就要从CPU上调度走,过一段时间又回来,此时需要沿着上次执行的结果继续执行,这个进程离开时,之前执行的中间结果会被相应的寄存器保存起来,用于下次使用,寄存器中保存起来的就叫进程的上下文。可以理解为:打游戏的存档~~当你游戏玩累了,不想玩了,此时可以存档,等下次你再想玩的时候直接读档即可

(4)进程的记账信息:在有优先级的前提下,不同的进程利用的系统资源是不一样的,操作系统会统计每个进程在CPU上执行的时间、内存使用情况等,根据这个记账信息,操作系统会进一步调整调度策略,做出优化,确保资源足够让每个进程正常执行

5. 虚拟空间地址

🔥 🔥早期的操作系统,程序运行时分配的内存就是物理内存,后面逐渐引入了 “虚拟地址空间”  这一概念,而不是直接去分配物理内存了,通过分配虚拟的内存空间,操作系统对于内存又进行了一层抽象。如下:

进程间通信🥬:

🍅通过上述方式,就可以把进程之间隔离开了,但是进程之间很多时候也需要相互配合完成某项工作,进程间通信和进程的独立性 并不冲突,系统提供公共空间(多个进程都能访问到),让两个进程借助这种公共空间来交互数据。

主要的通信方式:管道,共享内存,文件,网络,信号量,信号等。

 6. 线程

🍅多进程来实现并发编程,效果的确非常好,但是多进程编程模型,也有明显的确定,进程太重量,效率不高,创建、销毁、调度一个进程消耗时间比较多,为了解决该问题,就引入了 “线程(Thread)”,线程也叫作 “ 轻量级进程 ”。

线程与进程的关系:

  • 线程不能独立存在,而是要依附于进程(进程包含线程)、
  • 进程可以包含一个线程,也可以包含多个线程
  • 一个进程最开始的时候,至少要有一个线程,这个线程负责完成执行代码得到工作,也可以根据需要,创建出更多的线程,从而使当前实现 “并发编程” 的效果。
  • 进程是资源分配的基本单位,线程是调度执行的基本单位

线程的结构:每个线程也有状态,优先级,上下文,记账信息... ,可以独立的进行调度

上述结构决定了线程的特点:

  1. 每个进程都可以独立的去 CPU 上调度执行
  2. 同一个进程的多个线程之间,共用同一份 内存空间 和 文件资源...
  3.  由于可以共用同一份内存空间,创建线程的时候,就不需要重新申请资源了,直接复用之前分配给进程的资源,省去了资源分配的开销,于是创建效率更加高。      

总的来说:进程中包含线程 --> 一个进程由多个 PCB 共同表示 --> 每个 PCB 来表示一个线程 --> 每个线程都有自己的状态、上下文、优先级、记账信息 --> 每个线程都可以独立的去 CPU 上调度执行 --> 这些 PCB 共用了同样的内存指针 和 文件描述符表 --> 创建线程(PCB)不需要重新申请资源 --> 创建/销毁效率更高了

问题:线程一定是越多越好吗?

  • 最开始增加线程的数目,的确还能进一步提高效率
  • 当再一步增加线程数目,效率无法进一步提升了,反而会因为调度线程太多了,使调度的开销更大,反而会降低效率。
  • 而且线程数目过多时候,就会出现多个线程同时去抢同一个任务时候,产生冲突,此时就称为 "线程不安全问题"
  • 一个线程抛出异常,如果没有妥善处理就容易把整个进程都带走(崩溃),此时其他线程自然也就随之消亡。

🔥注:每个线程都是独立调度,在调度的时候,系统就不再考虑进程这样的概念了。

7. 进程与线程的区别📖

  1. 进程包含线程,一个进程里面可以有多个线程
  2. 进程和线程都可以用来实现 并发编程,但是线程 比 进程更轻量,更高效
  3. 同一个进程的线程之间共用同一份 资源(内存 + 硬盘),省去了申请资源的开销
  4. 进程和进程之间,具有独立性,一个进程挂了不会影响其他进程。而在同一个进程的多个线程是可能会相互影响(线程安全问题 + 线程出现异常)
  5. 进程是资源分配的基本单位,线程是调度执行的基本单位

💞 💞 💞那么本篇到此就结束啦,如果我的这篇博客可以给你提供有益得参考和启示,可以三连支持一下!!!

评论 72
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值