本篇将大致介绍linux操作系统的全貌,理解一些操作系统的基础概念,着重讲解程序、进程、线程、线程(协程)之间的区别
计算机启动过程
这里我们会简单的介绍计算机启动过程,不会去仔细扣其中的细节,大致了解即可
通电
首先,给计算机通电后,第一个起来的BIOS,BIOS第一件事情就是加电自检
在自检期间,BIOS会去检查计算机的这些硬件是不是出现了问题,例如它去检查内存插好没有,显卡插好没有…如果这些东西都没有插好,那么BIOS会发起警告
自检完成就会做BIOS做的最重要的事情就是加载BootLoader
BootLoader在一个硬盘上面是写死的,这样就可以保证BIOS这个硬件可以正确找到这个应用,然后将这个应用启动
BootLoader启动
- BootLoader就是我们俗称的引导程序,这个程序可以引导我们来启动操作系统,因为有可能我们电脑上面会不止安装一个操作系统,这些不同的操作系统启动就需要用户选择,当我们通过引导程序启动操作系统之后,以后所有的硬件和软件都会交给操作系统来管理了,这就像是大老板一样
操作系统基础知识
各操作系统简介
- 市面上有非常多的操作系统,例如Linux、自成一派的Mac、我们经常使用的WIndows,这些都是市面上非常有名的操作系统,除此之外还有号称要做物联网时代第一操作系统的鸿蒙操作系统
操作系统的作用
- 操作系统是一个软件,它的作用是管理硬件和管理其他软件。它可以一边管理硬件,一边对外提供应用的一些接口,我们用户想要对硬件进行一些操作全部需要通过操作系统,例如向磁盘中写文件、从网卡那边读传来的数据等等
操作系统的基本组成
Linux操作系统,最终要的有2个部分,一个是用户空间,一个是内核空间。内核空间是管理计算机底层硬件的;用户空间是运行用户程序的,内核空间非常重要,用户程序只能在经过了内核的同意后才可以访问内核空间
内核要干的事情特别多
这里面内核要干的最重要的事情就是进程调度,当然,这里的内核说的是宏内核,以上的事情全部都是宏内核要干的事情,与宏内核相对的就是微内核
微内核的典型就是鸿蒙系统,这个微内核的最低配就只有一个功能,就是内核最核心的功能——进程调度
假如我一个程序访问宏内核,想要往磁盘上写一个内容,这个时候我们向内核发送的请求会被内核接收到,这个宏内核就会自己调用功能,然后再通知应用,写的结果;
如果我们程序访问的不是宏内核,而是微内核,那么就有可能这个微内核种没有这个功能,于是这个微内核就会向其他的核心发起询问,找寻到底哪个核心有这个功能,如果说它发现,欸,这个电视机有这个功能,内核就会通知电视机干这件事,干完以后将结果返回,最后再由内核返回结果给程序。
从这里我们就可以感受到一些万物互联的味道了,微内核比起宏内核来说就更加的灵活,它可以适配不同的硬件调整内核大小,例如它可以像安装插槽一样动态定制功能,假如我这个硬件空间足够,那么我这个微内核就可以在除了进程调度以外添加上内存管理功能,非常灵活
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读取到内存中,这个时候程序就会在内存中被单独开辟一个空间出来
进程与线程区别
当程序进入到内存后就会变成一个进程
那么进程与线程的区别在哪里呢?我们使用两种方式来解释,一种是白话文,一种是专业描述
- 进程是一个程序运行起来的状态,线程是进程中的可执行路径
- 进程是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特别优越的地方了
文档信息
- 本文作者:JunHua yin
- 本文链接:https://yin-JH.github.io/2021/04/01/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E5%9F%BA%E7%A1%80%E7%B3%BB%E5%88%97(%E4%BA%8C)%E4%B9%8B%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%9A%84%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5%E4%B8%8E%E8%BF%9B%E7%A8%8B-%E7%BA%BF%E7%A8%8B-%E7%BA%A4%E7%A8%8B%E5%8C%BA%E5%88%AB/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)