1. 操作系统
2. 操作系统的功能
3. 什么是进程?
4. 操作系统对进程的管理
5. 进程控制块(PCB)的属性
6. 并行和并发
7. 进程间通信
8. 什么是线程?
9. 引入多线程
面试重点:进程和线程的区别与联系
通俗地讲, 操作系统需要同时管理计算机的硬件和软件, 因此, 操作系统在计算机内部的地位大概是这样的:
操作系统中提供的功能是非常复杂的, 我们暂时重点认识一下操作系统对"进程"这个软件资源的管理.
2. 进程是操作系统进行资源分配的基本单位.
3. 运行一次可执行文件, 操作系统就会创建一个对应的进程, 关闭一个可执行文件时, 操作系统就会销毁其对应的进程.
这里的描述使用的就是C语言中的结构体(操作系统主要是通过C/C++来实现的), 操作系统中描述进程的结构体, 我们称之为PCB(process control block), 也就是进程控制块.
再组织若干个进程(使用一些数据结构, 把很多描述进程的信息放在一起, 方便进行增删改查)
以Linux操作系统为例, 组织进程最典型的实现就是通过双向链表将每个进程的PCB连接起来,
“创建线程”, 就是先创建出PCB, 然后将PCB连接到双向链表中
"销毁进程"就是找到链表上该进程的PCB并删除
"查看任务管理器"就是遍历链表
要想进程正常工作, 操作系统就需要为进程分配一些系统资源:内存, 硬盘, CPU
在讲剩下的属性之前, 我们先引入一个概念:什么是进程调度?
现在的CPU一般有6核, 8核, 16核等, 如果一个CPU核心管理一个进程, 那么一台计算机能同时运行的进程数就十分有限, 如何让少量的CPU核心同时运行多个(几十个, 甚至上百个)进程, 并且这些进程都能被分配到合适的资源, 这件事情就叫做"进程调度".
上面的属性都是PCB的基础属性, 下面的属性主要是为了实现进程调度.
并行:多个CPU核心, 同时执行多个进程(举例:我在写博客, 我舍友正在浏览不良网站, 那么我和我舍友之间就是并行的)
并发:一个CPU核心, 先执行进程A, 再执行进程B, 再执行进程C, 再执行进程A…虽然这些进程是按次序被执行的, 但切换的速度非常快, 一次运行的时间非常短, 以至于看起来就像是在同时执行三个进程一样, 这就是并发
注意:并行和并发的区别仅限于微观层面, 在宏观层面上我们无法看到这两个的区别, 并且, 只有在研究操作系统时, 我们才会对并行和并发有所区分, 在其他场景中, 并行和并发统称为并发.
操作系统中通过虚拟地址空间来存储进程, 这样做的好处是将进程并联起来, 一旦一个进程出现bug或者出现崩溃, 也不会影响到其他进程, 确保了进程间的独立性.
但是, 在实际工作中, 我们往往需要在多个进程之间进行交互, 但进程都被虚拟地址空间隔离起来了, 我们如何实现进程间的交互(也就是进程间通信)呢?
操作系统为进程间通信提供了专门的公共空间, 现在最常用的进程间通信方式有两种, 分别为:
这两种我们后面都会学到.
如何解决这样的问题?
方法一:创建一个进程池
通过创建进程池可以大幅度地提高效率, 但问题是, 进程池里的闲置进程在不使用时也会消耗内存资源, 这样对内存的消耗非常大.
方法二:通过多线程来实现并发编程
线程比进程更轻量(一个进程包含一个或多个线程), 每个进程可以执行一个任务, 每个线程也可以执行一个任务, 也能实现并发编程. 并且, 创建线程, 销毁线程, 调度线程的成本要比进程低得多.
为什么进程比线程更轻量?
进程的重, 是重在资源的申请和释放, 进程对资源的申请和释放就好比在一个庞大的仓库中找一个自己想要的东西, 效率非常低下, 而线程是包含在进程中的, 由于一个进程中的多个线程共用一份资源, 因此只有在创建第一个线程时需要分配资源, 后续这个进程中创建线程时就不需要再分配资源了, 大大节约了成本.
既然这样, 是不是线程越多就越好呢?
当然不是, 如果线程多了, 这些线程可能要竞争同一个资源, 这时整体的速度就受到了限制.
进程中包含线程, 一个进程中可以有一个线程, 也可以有多个线程
进程和线程都是为了处理并发编程这样的场景, 但进程频繁创建和释放资源的效率比较低, 相比之下, 线程更轻量, 创建和释放效率更高
(为什么线程更轻量? 少了资源申请和释放的过程)
操作系统创建进程, 需要给进程分配资源, 进程是操作系统分配资源的基本单位, 操作系统创建的线程, 是要在CPU上调度执行, 线程是操作系统调度执行的基本单位.
进程具有独立性, 每个进程具有自己独立的虚拟地址空间, 一个进程崩溃不影响其他进程, 而同一个进程中的多个线程共用一个存储空间, 一个线程崩溃可能会影响其他线程, 甚至可能会导致整个进程崩溃.