目录
1. 操作系统功能简介
2. 进程
2.1 认识进程
2.2 进程操作系统中如何管理
2.3 PCB如何描述
2.3.1 pid
2.3.2 内存指针
2.3.3 文件描述符表
2.3.4 进程调度相关属性
3. 内存管理
4. 线程
4.1 认识线程
4.2 进程与线程的关系
4.3 线程安全问题
操作系统是一个做管理工作的软件,管理硬件设备并且为软件提供稳定的运行环境
操作系统是软件和硬件用户之间交互的媒介
常见的操作系统:Windows 98,2000,xp,vista,win7,win10,win11
Linux:特别适合开发与部署的操作系统
Mac:苹果电脑使用的操作系统
Android,IOS等,都是常见的操作系统
我们看一下操作系统的层次结构
层次 | 说明 |
应用程序 | java就属于应用程序的一部分 |
系统调用 | 操作系统给应用程序提供API(程序操作硬件设备时,先通过系统调用,把操作命令给系统内核,其次内核调动驱动程序,来操作硬 件设备) |
操作系统内核 | 操作系统的功能(管理) |
驱动程序 | 硬件设备,种类繁多,厂商各异,厂商在开发硬件时会提供驱动程序,电脑安装驱动程序后才能正确识别硬件设备 |
硬件设备 | 打开电脑后盖,看见的就是硬件设备 |
进程(process)也叫任务(task),(ctrl+alt+delete)打开任务管理器,就可以看到电脑正在运行的程序
因此,一个跑起来的程序就是一个进程
电脑上有很多程序,没有运行起来的,就不是进程,双击运行它,就会创建进程
还可以看到,每一个进程,都对应了电脑所分配的资源,进程是操作系统资源分配的基本单位
当运行的进程足够多时,电脑的资源就会被全部占用,这个时候电脑就变得非常卡顿
所以电脑卡顿和电脑硬盘存储的东西多不多没关系
进程是一个重要的软件资源,是由操作系统进行管理的
管理方式:描述+组织
描述:进程控制块 (PCB:Processing Control Block),使用结构体描述进程属性,不是PCB (printed circuit board)印制线路板
组织:通过一定的数据结构(双向链表)把多个pcb串起来
创建一个进程,本质上是创建一个PCB这样的结构体对象,然后插入到链表中
销毁一个进程,本质上是删除掉链表上的PCB节点
任务管理器上查看进程列表就是遍历这个链表所获得的
pid是进程身份标识符(唯一的数字),每个进程都对应一个pid
勾选pid就能看到
指向进程使用的资源
硬盘上的文件等其他资源
也描述了进程使用了哪些资源
硬件资源,比如内存,硬盘,网卡这些是好划分的,不好划分的是cpu资源
电脑上运行的进程有很多,cpu却很少,打开设备管理器就能看到处理器
这些进程希望能''同时运行''''分时复用''
并行:微观上同一时刻,两个核心上的进程是同时执行的
并发:微观上同一时刻,一个核心只能运行一个进程,但能对进程快速切换(宏观上就觉得这些进程是同时在运行的)
并行或并发统称为"并发",是由内核负责处理,应用程序感知不到
操作系统中的调度器负责让有限的cpu资源来调度执行很多的进程
处理机:计算机系统中存储程序和数据,并按照程序规定的步骤执行指令的部件。 处理机包括中央处理器,主存储器, I/O 接口。 处理机再加上外围设备eg:鼠标.键盘.等构成完整的计算机系统。
1.进程的状态
就绪状态:
指的是进程已经处于准备好运行的状态,即进程已经分配到除了cpu资源以外的所有必要资源,只要分到cpu,就能立即执行
如果系统中有多个就绪队列,会按照优先级将他们排成一个就绪队列
执行状态:
指的是进程已经获得cpu,程序正在执行的状态
单处理机只有一个进程处于执行状态
多处理机有多个进程处于执行状态
阻塞状态:
正在执行的进程由于发生(IO请求,申请缓冲区失败等)暂时无法继续执行的状态,即执行的过程受到阻塞了,操作系统会把处理及分配到另一个就绪状态的进程,让受阻塞的进程暂停运行,这种状态就是阻塞状态
2. 优先级
进程也是有优先级的,操作系统进行调度的时候,要了解京城的状态及调度信息,进程优先级就是一个描述进程使用处理机的优先级别的一个整数,优先级高的进程优先获得处理机
3. 上下文
处理机状态信息也称为处理机的上下文,上下文也就是处理机的各种存储器中的信息组成的,是程序运行的中间结果.
主要作用是:
当进程被切换的时候,处理机的状态信息也即上下文必要保存在相应的PCB中,以便于该进程重新执行时能再从断点处继续运行
保存上下文:把CPU中的寄存器的值保存到PCB
恢复上下文:把这些值恢复到寄存器中去
4. 记账信息
操作系统,统计每个进程在CPU上占用的时间和执行的指令数目,根据这个决定下一阶段是如何调度的
如何理解内存?
物理上是一个内存条,可以存储很多数据
内存可以想象成一个大走廊,有很多小房间,每个房间大小1Byte,并且房间还有编号从0累加,这个内存编号就是地址,这个地址是"物理地址"
内存有一个随机访问的特性,访问内存上的任意数据速度都很快,这个特点造就了数组访问时间复杂度事O(1)
实际上程序并不能直接获取到物理内存
这里我们引入了"虚拟地址空间"
直接使用物理内存地址,如果程序出现bug,影响是十分严重的,可能导致访问的内存越界,如果进程一出现访问越界,可能会影响到到进程二的执行,是因为进程之间使用的内存没有进行隔离开,所以可能会相互影响到
针对这个问题引入了''虚拟地址空间'',代码里不直接使用真实的物理地址,使用虚拟出来的地址
由操作系统和专门的硬件设备负责进行虚拟地址到物理地址的转换
如果进程一访问越界了,指针地址改变了之后,MMU硬件设备会及时的反馈一个错误,当前地址超出了进程一访问的范围,因此返回一个SIGN SEGEMENT FAULT信号,引起进程一崩溃
所以引入虚拟地址空间,主要是为了避免进程之间相互产生影响,也就是谁出bug了谁就崩溃,每个进程之间就是隔离的了,具有非常重要的意义
MMU是集成在cup中的硬件设备
这样虽然解决了进程间相互影响的问题,但是进程间也是需要数据交互的,所以需要一个"公共空间"来进行数据交互,就能解决进程间的通信问题
引入进程是主要目的是为了解决"并发编程"问题,当前cpu进入了多核心时代,为了进一步提高程序的执行速度,就要利用好多核cpu
但是进程消耗的资源和速度相对于线程来说还是慢了很多,进程在资源的分配和回收上的开销非常大,因此线程应运而生,线程也叫做"轻量级进程",它既能解决并发编程的问题,又同时能让创建销毁调度的速度更快一些
线程的轻量在于线程不用申请资源和释放资源,减小了很大一部分开销
每创建一个进程,就好像创建一个工厂,在进程创建一个线程,就好像在一个工厂里增加多条生产线,多条生产线公用一个资源,达到了资源复用的目的
进程与线程的关系:进程包含线程,一个进程可以包含多个线程,也可以只包含一个线程(不能没有)
当第一个线程启动后,开销是比较大的,但是后面的线程使用的是和第一个线程相同的资源,开销比较小
那么线程使用的资源是哪些?
同一个进程里的所有线程之间,公用的资源:进程拥有的资源,主要包括内存,文件描述符表
也就是线程一申请的内存,后面的线程可以直接使用,线程一打开的文件,后序线程也可以直接使用
发展到现在,操作系统实际调度的时候,是以线程为基本单位来调度的,调度进程就相当与一个进程只有一个线程的情况,如果每个进程有多个线程了,每个线程是在cpu上独立进行调度的
因此,线程是操作系统调度执行的基本单位,每个线程都有自己的执行逻辑
一个线程也是通过PCB来调用的,所以一个进程可能包含多个PCB,但是同一个进程的pid是一样的,内存指针和文件描述符表也是相同的
一个进程是可以包含多个线程的,但是增加线程的数量时,也不是一直能提高执行速度,因为cpu核心数量时有限的,线程太多了,核心数目有限,线程调度将会是很大的开销了
系统创建也是需要消耗资源的,创建过多的线程,会导致资源耗尽,别的进程也无法使用了,像cpu,内存,带宽这样的资源
还有一种情况,在不同进程中,每个进程都有自己的资源,不会出现争夺资源的问题,他们的资源都是创建的时候就分配好了,但是线程模型是资源共享的,很容易就触发多线程争抢同一个资源,即一个进程中会出现多线程同时使用一个资源的情况,造成了线程不安全问题
多线程还有另一种情况,当一个线程抛出异常,如果没有处理好,整个进程可能都会崩溃,那么其他线程也寄了