操作系统基础系列(二)之操作系统的基础概念与进程、线程、纤程区别

2021/04/01 Operating_System 共 3426 字,约 10 分钟

本篇将大致介绍linux操作系统的全貌,理解一些操作系统的基础概念,着重讲解程序、进程、线程、线程(协程)之间的区别

计算机启动过程

这里我们会简单的介绍计算机启动过程,不会去仔细扣其中的细节,大致了解即可

通电

  • 首先,给计算机通电后,第一个起来的BIOS,BIOS第一件事情就是加电自检

    在自检期间,BIOS会去检查计算机的这些硬件是不是出现了问题,例如它去检查内存插好没有,显卡插好没有…如果这些东西都没有插好,那么BIOS会发起警告

  • 自检完成就会做BIOS做的最重要的事情就是加载BootLoader

    BootLoader在一个硬盘上面是写死的,这样就可以保证BIOS这个硬件可以正确找到这个应用,然后将这个应用启动

BootLoader启动

  • BootLoader就是我们俗称的引导程序,这个程序可以引导我们来启动操作系统,因为有可能我们电脑上面会不止安装一个操作系统,这些不同的操作系统启动就需要用户选择,当我们通过引导程序启动操作系统之后,以后所有的硬件和软件都会交给操作系统来管理了,这就像是大老板一样

操作系统基础知识

各操作系统简介

  • 市面上有非常多的操作系统,例如Linux、自成一派的Mac、我们经常使用的WIndows,这些都是市面上非常有名的操作系统,除此之外还有号称要做物联网时代第一操作系统的鸿蒙操作系统

操作系统的作用

image

  • 操作系统是一个软件,它的作用是管理硬件和管理其他软件。它可以一边管理硬件,一边对外提供应用的一些接口,我们用户想要对硬件进行一些操作全部需要通过操作系统,例如向磁盘中写文件、从网卡那边读传来的数据等等

操作系统的基本组成

image

  • Linux操作系统,最终要的有2个部分,一个是用户空间,一个是内核空间。内核空间是管理计算机底层硬件的;用户空间是运行用户程序的,内核空间非常重要,用户程序只能在经过了内核的同意后才可以访问内核空间

  • 内核要干的事情特别多

    image

    这里面内核要干的最重要的事情就是进程调度,当然,这里的内核说的是宏内核,以上的事情全部都是宏内核要干的事情,与宏内核相对的就是微内核

    微内核的典型就是鸿蒙系统,这个微内核的最低配就只有一个功能,就是内核最核心的功能——进程调度

    假如我一个程序访问宏内核,想要往磁盘上写一个内容,这个时候我们向内核发送的请求会被内核接收到,这个宏内核就会自己调用功能,然后再通知应用,写的结果;

    如果我们程序访问的不是宏内核,而是微内核,那么就有可能这个微内核种没有这个功能,于是这个微内核就会向其他的核心发起询问,找寻到底哪个核心有这个功能,如果说它发现,欸,这个电视机有这个功能,内核就会通知电视机干这件事,干完以后将结果返回,最后再由内核返回结果给程序。

    从这里我们就可以感受到一些万物互联的味道了,微内核比起宏内核来说就更加的灵活,它可以适配不同的硬件调整内核大小,例如它可以像安装插槽一样动态定制功能,假如我这个硬件空间足够,那么我这个微内核就可以在除了进程调度以外添加上内存管理功能,非常灵活

Intel提供的不同分级与Linux分级

  • 从硬件层面,intel给不同的指令分了访问的级别,一共分为4个级别,分别是 ring 0、ring 1、ring 2、ring 3,其中保护级别最高的是ring 0
  • linux也运用了Intel的分级,不过只用了其中的两个级别,分别是ring 0和ring 3,其中ring 0被运用到了内核态,ring 3被运用到了用户态。内核态的linux可以访问ring 0级别的指令;用户态只可以访问ring 1级别的指令
  • 当用户想要访问ring 0级别的一些操作,那么就会从用户态切换到内核态,完成后从内核态切换回用户态,这就是切换,这也是要消耗资源的

程序、进程、线程、纤程的介绍

程序概念介绍

  • 程序的解释非常简单,我们这里用一个白话文的形式来介绍

    程序就是静静躺在硬盘上的一段代码,例如qq.exe,当我们双击exe文件,那么操作系统就会将这个程序通过IO读取到内存中,这个时候程序就会在内存中被单独开辟一个空间出来

进程与线程区别

  • 当程序进入到内存后就会变成一个进程

  • 那么进程与线程的区别在哪里呢?我们使用两种方式来解释,一种是白话文,一种是专业描述

    1. 进程是一个程序运行起来的状态,线程是进程中的可执行路径
    2. 进程是CPU分配资源的基本单位,线程是CPU执行调度的基本单位
  • 为什么说进程是CPU分配资源的基本单位?

    • 我们开始的时候就提到过了,当我们双击一个程序的时候,这个程序就会被加载到内存,并且在内存种被分配一片空间,这里被分配的一片空间就是最重要的,进程被分配的资源。当然,一个进程除了被分配内存空间地址这个资源以外,还会被分配寄存器、ALU、PC等
    • 从这里我们也可以感受到,进程的确是CPU分配资源的基本单位
  • 为什么说线程是CPU执行调度的基本单位?

    • 当我们在程序中启动多个线程的时候,那么对于CPU来说,这些线程都是可以执行的,CPU会或随机或有规律地挑选线程来执行,一个线程执行一段时间就会被调度,切换其他的线程来执行,这就是线程是CPU执行调度的基本单位的意思
  • 线程和进程的本质区别

    • 线程和进程的本质区别在不同的操作系统中是不一样的,我们先来谈谈Linux中的区别

      在Linux中,进程和线程基本没有区别,当Linux启动一个线程,其实就是调用fork()方法启动子进程,对于Linux来说,进程是拥有自己独立空间的,但是线程却是一个程序中的所有线程公用一块空间,这就是在linux中进程和线程的区别

    • 如果不是linux系统的话,那么线程就有可能会是一个轻量级的进程(Light Weight Process)简称lwp

僵尸进程与孤儿进程

我们知道,进程的管理是通过PCB管理的,通过PCB可以管理进程的状态

  • 僵尸进程

    当一个进程的子进程运行完毕被释放了资源后PCB没有被删除,也就是说虽然父进程维护着子进程的PCB,但是这个子进程已经被释放了,父进程就像只维护了一个牌位一样,这就是僵尸进程

    僵尸进程的影响其实不是特别大,因为子进程的资源已经被释放了,只剩下一个PCB,所以影响不是特别大,但是如果僵尸进程实在太多了,还是有影响的,因为PCB也是要占有空间的

  • 孤儿进程

    当一个进程的父进程结束了,但是这个进程还没有结束,这就是孤儿进程,孤儿进程会改变自己的父进程,孤儿进程都会交给1号进程维护,孤儿进程对linux的影响其实也不大,只不过换了个爹而已

纤程介绍

  • 纤程(fiber),又被称为协程,是一个轻量级的线程,可以说是线程中的线程。
  • 假如我们想要启动一个线程的话,我们需要切换到内核态,然后在内核态启动一个线程,这个线程的资源消耗基本等于一个进程;但是如果我们想要启动一个纤程,那么这个纤程的启动不需要经过内核态,只需要在线程中进行控制即可

线程与纤程的资源消耗

  • 启动一个线程,基本需要消耗1M
  • 启动一个纤程,只需要4k

纤程的内部实现逻辑

  • 其实纤程的内部实现和线程实现是一个道理
  • 例如在JVM层次,我们就把JVM的线程当作是内核,JVM的线程中有JVM Stacks,我们就可以模仿这个结构,也制作小型的stack交给纤程使用,纤程的调度就和线程调度的逻辑一样,只不过负责它调度的不是内核,而是线程

线程与纤程的调度

  • 当我们的应用程序创建了非常多的线程的时候,我们的CPU会需要进行线程调度,首先我们会切换到内核态,在内核态完成线程切换,切换完毕后再切换回来
  • 如果我们创建的是纤程的话,那么我们纤程的切换不需要进行内核态转换,仅仅只需要线程就可以对纤程进行调度,速度非常快
  • 下面我们举例来说明线程和纤程的调度
  • 首先,我们启动了10w个线程,每一个线程都进行一个固定的计算操作(不涉及到内核);接着我们启动1个线程,在这个线程里面启动10w个纤程同样每个纤程都进行固定的计算操作。最后经过压测后,一个线程启动的10w个纤程比直接启动10w个线程的效率要高6.6倍左右(使用线程的花费180s,使用纤程耗费27s),这还不是最完美的纤程运用,如果要更加完美的话,我们还可以启动10个线程,每一个线程中启动10k个纤程,那么就可以最大效率利用我们的cpu,效率提升会更高恐怖!

浅谈Java纤程

  • 目前支持内置纤程的语言有很多,出名的就有 kotlin、scala、go等等。非常遗憾,直到今日 2021/4/1日,Java SE 16仍然没有支持内置纤程
  • 网上有很多人说go语言比Java优秀,其实优秀就优秀在纤程上面,如果Java也支持纤程的话,go语言就没有比Java特别优越的地方了

文档信息

Search

    Table of Contents