目录
操作系统基础扫盲(基础)
- 啥是操作系统??
操作系统是一个非常复杂的软件. 操作系统对上要为各种软件资源提供稳定的环境,操作系统对下要管理各种硬件设备
- 操作系统的基本组成
操作系统包括 cpu(操作系统的核心) 输入设备 输出设备 存储器(内存和外存)
- 操作系统层级关系
- 应用程序 : 我们平常使用的软件
- 系统调用 : 时操作系统提供的一些列API
比如我要想在控制台输出信息 ,就会调用 库函数, 操作系统就会调用系统调用的 API write , 调用write进入系统内核 ,操作系统内核进一步控制硬件进行输出
- 操作系统内核
操作系统内核是操作系统最核心的一部分当我们使用系统调用进入系统内核时,有时就会在用户态和内核态之间进行切换,由于操作系统只有一个内核,而应用程序就有多个,所以在一个程序执行时就会有多个程序在进行排队等待
啥是进程
由于我们编写的代码是一些静态文件,当运行程序时会将文件编译成可执行的二进制文件,将它装载到内存中,这个运行的程序就是一个进程. 比如 我们打开QQ,这个QQ就是一个进程
进程管理
我们在电脑上可以运行很多程序,就会有很多进程,我们要对这些进程进行管理,这就是进程管理.
如何进行管理 ?
我们将进程利用一个结构体/类 进行描述 这也叫 进程控制块 PCB ,我们使用双向链表的数据结构将多个PCB串联一起.
pcb包含的信息
- PID : PID是pcb的唯一身份标识
- 文件描述表 : 文件描述表就描述了进程都打开了哪些文件,当我们使用文件函数打开文件时就会给表添加个表项,就相当于一个顺序表,每个元素都是打开的文件,元素下标就是文件描述符
- 内存指针 : 操作系统会将一些关键信息(包含一些指令和数据)加载到内存中,而内存指针就描述了哪些是指令,哪些是数据
文件描述表 描述了系统有哪些硬件资源 ,内存指针描述了系统有哪些内存资源 --->这两个资源就描述了操作系统有哪些资源.
我们把进程称为 为系统进行 "资源分配" 的基本单位.
- 一些关于进程调度的关键属性 进程的优先级 进程的状态 进程的记账信息 进程的上下文
进程调度
- 为啥要进行调度??
因为在操作系统中 CPU 少 ,而进程非常多,这就导致有的进程没有在CPU上执行,所以这种状态可以类比 "狼多肉少",解决这个问题 操作系统就要对进程进行一些调度
- 怎么进行调度呢???
让每个进程 "轮流式"的在CPU上运行, 这种轮流式的运行 我们称为 并发执行
并发在微观上是 "轮流式"的在CPU上运行,而因为切换进程太快导致我们认为是同时执行.
- 啥是并发? 啥是并行
并发在宏观上是 同时执行 微观上是让其进程在CPU轮流式的执行;
并行在宏观上是同时运行 微观上也是同时进行.
- 关于进程调度的一些属性
这里举一个小栗子:
把我当成一个时间管理大师 我是一个女生 同时要对三个男生进行交往,A(有钱) B(长得帅) C (会说话) .我每周都要给这三个男朋友进行安排时间
进程的优先级
举例 : 由于A男友非常有钱,我就很怕失去他,所以给他安排的时间多一点,又因为B长得帅 也是我说倾向的一个 所以其次给他安排时间 最后剩下的时间就安排给C
对于进程来说,操作系统并不是一视同仁,哪个进程重要,就要对这个进程优先调度.也要有一个优先级
进程的状态
举例 : 在安排时间时候,突然A告诉我他要出差一周,所以在安排时间时只能给B,C安排时间,对于A就是处在阻塞状态,而B,C处在就绪状态,当与B在一起时 B就是处在运行状态;
对于进程有5种状态
- 创建状态
进程处于被创建时的状态
- 运行状态
进程时刻处在CPU上运行
- 就绪状态
由于有其他进程在运行,就导致停止运行,等待其他进程在CPU上结束执行,进程随时课上CPU运行,处于就绪状态
- 阻塞状态
因某一时间发生(如磁盘的读写) 导致进程暂时停止运行,等待某一事件完成后,在上CPU上执行
进程的记账信息
举例: 我们每一周对齐分配时间时就会检查以往的时间分配情况,此时我们发现给C男朋友安排时间太少,这时就会在下周安排时间时调整一下策略
对于操作系统来说,在安排进程时会记录以往对进程在CPU安排的时间(时间时长或者指令数),发现某些进程安排在CPU时间少,就会调整策略
进程的上下文
举例 : 比如 我想吃一道菜 我就会让男盆友给我做,男朋友会在网上找到一些资源怎么做这道菜,有哪些原料,先放啥后放啥. 当男盆友在做饭时 做一半 我又说我想和可乐,然后男盆友立马放下手里的活,先下楼买可乐 ,等到回来买完可乐接着继续做刚才没做完的菜,此时买可乐相当于执行另一个任务,执行(买可乐)任务之前取消记录做菜做到哪,然后在去买可乐
对于进程也一样,CPU可以在进程之间进行切换,在切换之前必须记录当前进程运行状态的信息,以备下次切换回来时继续执行. 这个记录当前进程的运行状态信息就是上下文
进程的虚拟地址空间
- 为啥会有虚拟地址空间 ? ? ?
在c语言中,我们访问一块内存需要利用指针来访问,但是指针有一个缺点就是容易指错地方(指骗了),所以在指针解引用时导致访问失败 -->野指针问题,这个问题就会导致当我们打开一个程序时,另外一个程序崩了的问题.所以我们引出了虚拟地址空间的概念,让每个进程的内存指针都指向一块虚拟内存(每个进程执行时互相不受影响,就算出现野指针情形,其他进程不受到影响,而会将问题限制到出问题的线程内部.
每个进程之间不受其他进程之间的干扰,每个进程指向自己的虚拟内存空间,通过MMU映射,映射到对应物理上的(真实的)内存空间.当一个进程指错了(也就是物理内存空间没有这块内存空间) 映射到MMU,MMU就知道这块内存出问题,将消息个操作系统,操作系统会发出一个信号告知对应的进程内存访问失败. 每个进程之间不受影响--->进程的独立性.
- 这里还会有一个问题 对于进程过多,导致多个进程的虚拟内存空间加起来超过真实内存?
同一时刻,执行的进程数量很少
同一时刻,执行的进程很少情况将虚拟地址空间同时占满
就算在极端情况下,总的虚拟地址空间内存超过物理内存-->算做bug需要进一步处理(做一些优化或者换一个内存更大的机器);
进程间通信
进程间通信指的是 进程之间进行一些合作.
但是对于引出虚拟地址空间也就是多个进程之间不受到干扰(隔离性) 就会导致无法让多个进程之间合作.
那么如何在隔离性的情况下进行通信呢??
由于内核空间是多个进程之间共享的,要进行通信就需要通过内核.
进程间通信的方式
管道 信号量 消息队列 共享内存 socket 信号
线程
- 啥是线程 ?
我们前面知道进程是一个正在运行的一个程序,而线程可以理解为是进程在独立运行时的子任务(比如下载文件 ,发消息,发视频 这些子任务都是一个线程,并且能同时执行),也可以理解为线程是进程的"逻辑执行流" 一个线程可以执行单独的一段代码,多个线程之间是并发执行的
可以将工厂比作一个进程,而线程就相当于工厂中的多个流水线
进程中包含多个线程,一个进程的多个线程之间在并发执行
- 为啥要进行并发编程 ?
并发编程就是让CPU执行的更快(程序运行的更快)也就是多个任务一起执行,由于单核CPU已经发挥到极致,如果再想提高算力,就需要充分利用CPU的多核资源.
- 既然是多个任务一起执行 多个进程可以么?
在同一时刻多个进程一起执行,就会对进程进行频繁的创建和销毁,而创建一个进程(1.创建一个pcb 2. 为进程分配系统资源3.将pcb加入到内核的双向链表中) 由于需要为进程分配系统资源也就是在系统内核上做一些遍历操作 就会使得开销很大.所以不使用多进程.
- 啥是多线程 ? 为啥使用多线程 ?
多线程就是多个线程之间并发执行 .一个进程包含多个线程,一个进程的多个线程之间是共用进程的所有资源,也就是创建线程不必分配系统资源,这也就是线程轻量级的原因.->线程也叫作轻量级进程
操作系统在进行调度时是以线程为单位进行调度
线程调度比进程调度开销小 创建线程比创建进程开销小 销毁线程比销毁进程开销小
进程是资源分配的基本单位 线程是系统调度的基本单位
- 多线程是线程数越多越好么 ? 在采用多线程执行是会面临哪些问题
当线程数越多时,CPU多核已经被充分利用,会导致CPU被吃满,继续增加线程数不但不会增加效率,而且还会增加调度的开销. 多个线程之间,如果一个线程崩溃,就会导致一个进程之间的多个线程全部崩溃,就导致一个进程崩溃
这里可以理解为多个人吃席 ,由于人很多但菜不够那么多人分的,就会导致有人没有菜吃抢不过人家,这个人可能会生气抢不着菜吃就有可能会掀桌子导致一桌子人都吃不上饭.
线程与进程的区别
从描述的侧重点来说 : 进程是 "资源分配"的基本单位 线程 是 "系统调度" 得基本单位
从从属关系上来看 : 一个进程包含多个线程,一个进程的多个线程之间是并发执行的
从影响关系上看 : 一个进程崩溃,对其他进程没有影响,每个进程之间是相互独立的,一个线程崩溃可能会导致整个进程崩溃
从资源共享上来看: 进程之间是相互独立的不进行资源共享,每个进程包含一个虚拟内存空间,堆,栈,文件描述表 ,而线程之间共用进程的所有资源.
从上下文切换上来看 : 进程切换上下文速度慢,而线程切换上下文速度快 .
学完本篇文章回答如下问题 :
1.进程是指一个正在运行的程序,操作系统会将它加载到内存中,线程可以理解为进程运行时的独立子任务,一个进程包含多个线程,一个进程之间的多个线程是并发执行的.
2.在进行并发编程时由于单核CPU已经达到极致,要想提升算力,就需要充分利用CPU多核,由于在某些场景下需要等待io,为了在等待IO时最大限度的利用CPU执行一些其他的任务.而对于进程来说在某些场景需要频繁的创建和销毁进程是CPU效率极大的降低,而引出了线程,一个进程之间的多个线程共用进程的所有资源,使得创建线程不需要分配系统资源.线程又为轻量级进程
3.从描述侧重点上来看 : 进程是 资源分配的基本单位 线程是 系统调度的 基本单位
从从属关系上来看 : 一个进程包含多个线程,一个进程的多个线程之间是并发执行的
从资源共享上来看 : 一个进程有 虚拟内存空间,文件描述表,堆,栈等信息,多个进程之间是相互独立的,而一个线程共用一份系统资源,共用一份虚拟内存空间.文件描述表
从影响关系上看 : 多个进程之间是独立的,一个进程崩溃不会影响其他进程,但线程是共享进程的所有资源,一个线程崩溃,可能会导致整个进程都崩溃
4.并发从宏观上看是同时执行的,微观上看是"轮流式"的执行
并行从宏观和微观上看都是同时执行的
5.多进程是多个进程在同时运行 多线程是一个进程的多个任务在同时运行
6.同2
7.并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、死锁、线程不安全等等