一.冯诺依曼体系
- CPU中央处理器,进行算数运算和逻辑判断
- 存储器:分为内存和外存,用于存储数据(使用二进制的方式进行存储)
针对存储空间
硬盘 > 内存 >> CPU
针对数据访问速度
CPU >> 内存 > 硬盘
计算机在计算加减乘除的时候,都是靠加法器
数据在内存中的存储:存补码(目的是为了把加法和减法都统一成加法)
代码最终是在 CPU 上执行的,这些编程语言写的代码最终会被编译器/解释器,转换成 CPU 能认识的指令.
二.内存和外存
外存:硬盘,软盘,光盘,U盘…
内存 VS 外存:
- 内存比较小,外存比较大
- 内存访问速度快,外存访问速度慢.(差3-4个数量级)
- 内存贵,外存便宜…
- 内存的数据是一份临时的,像是全局变量那些,就是保存在内存中的,如果程序重新关闭,那么数据就没了.而外存的数据是永久保存的,持久化存储
关于持久化存储:
存在内存的数据不是持久化的
存在外存的数据就是持久化的(磁盘,数据库…)
计算机的最小存储单位是字节(Byte)
内存的一个非常重要的特点:支持随机访问
也就是可以随心所欲地访问内存中的任意地址的数据(开销极小)
CPU的寄存器也能存储数据,但是空间极小
三.操作系统(OS)
1.概念
**操作系统是一组做为计算机资源管理的软件的统称.**目前常见的操作系统有: Windows系列,Unix系列,Linux系列,OSX系列,Android系列,IOS系列,鸿蒙等.
操作系统是一个负责管理的软件:
- 管理硬件设备
- 管理软件资源
计算机系统的分层视图:
2.什么是进程(Process)/任务(Task)
每个应用程序运行与现代操作系统之上,操作系统会提供一种抽象,好像系统上只有这个程序在运行,所有的硬件资源都被这个程序使用.这种假象是通过抽象了一个进程的概念来完成的,进程可以说是计算机科学中最重要最成功的概念之一.
进程是操作系统对一个正在运行的程序的一种抽象,换言之,可以把进程看做程序的一次运行过程;同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位
像qq那种exe文件叫做"可执行程序",而当这个程序运行起来就是一个进程
3.进程的生命周期
- 进程创建:系统初始化->用户请求创建一个进程->正在运行的进程执行了创建进程的系统调用
- 进程运行:内核选择一个就绪进程,让他占用处理机并执行(和处理调度算法有关)
- 进程等待(阻塞):进程只能自己阻塞自己,因为只有进程自身才能知道何时需要等待某种时间的发生.
- 进程唤醒:别的进程或操作系统将阻塞的进程PCB插入到就绪队列.
- 进程结束:正常退出,错误退出,致命错误(强制),被其他进程所杀(强制)
4.进程在操作系统中是被如何管理的
管理 = 描述+组织
1)描述(PCB):
进程控制块抽象(PCB,Process Control Block):操作系统管理控制进程运行所用的信息集合
计算机内部要管理任何现实事物,都需要将其抽象成一组有关联的,互为一体的数据.在Java语言中,可以通过类/对象来描述这一特征.
PCB里面含有的属性:
-
PID:一个进程的身份标识.一个机器同一个时刻,不可能有两个进程的 PID 相同
-
内存指针:描述了这个进程使用的内存空间是哪个范围(虚拟地址空间)
-
文件描述符表:描述了这个进程都打开了哪些文件.
系统打开一个文件,其实就得到了一个"文件描述符",这个文件描述符(整数)就像一个"遥控器一样".文件数据是在磁盘上的,代码中操作磁盘数据不像操作内存数据那么方便,所以往往是借助这种"遥控器"的方式来操作… -
进程的状态:
-
运行状态:当一个进程正在处理机运行时
-
就绪状态:一个进程活的除处理机之外的一切所需资源,一旦得到处理机即可运行
-
等待(阻塞)状态:一个进程正在等待某一事件而暂停运行
-
创建状态:一个进程正在被创建,还没被转到就绪状态之前我的状态
-
结束状态:一个进程正在从系统中消失时的状态
-
-
进程的优先级:
-
进程的上下文:需要记住上次运行到哪个指令了,方便下一次调度的时候能够继续从这个位置来运行(读档和存档)
主要是存储调度出 CPU 之前,寄存器中的信息.(把寄存器信息保存到内存中)
等到这个进程下次恢复到 CPU 上执行执行的时候,就把内存保存好的数据恢复到寄存器中. -
进程的记账信息:记录这个进程在 CPU 上执行了多久.用来辅助决定这个进程是继续在 CPU 上执行,还是说要调度出去了.
2)组织
PCB的组织一般是通过双链表,因为可能面临进程创建,销毁等调度导致进程状态发生变化,链表能够更加灵活的插入和删除
链表:同一个状态的进程其PCB成一链表,多个状态多个不同的链表.如就绪链表,阻塞链表…
3)并发和并行
-
并发式执行:并发(Concurrent),在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行.
由于 CPU 的运行速度极快,虽然 CPU 在一直进行切换,但是坐在电脑前的用户,是感知不到这个切换过程的
-
并行式执行:多个 CPU,运行多个进程,CPU1 运行 进程1,CPU2 运行进程2;进程1 和进程2 是同时进行的.
4)进程调度
由于抢占式执行的缘故,操作系统何时进行进程调度(啥时候把进程放到 CPU 上,啥时候把进程切换出 CPU),这个过程对于进程来说,是感知不到的
5.进程的虚拟地址空间
一个进程要想运行,就需要给他分配一些系统资源,其中内存就是一个最核心的资源
物理地址:真实的内存地址.
操作系统会直接依据真实的内存地址进行划分空间,分配给每一个进程.
虚拟地址,顾名思义非真实的地址.如上图
一个/一块虚拟地址和真实地址之间是一一对应的关系.
为啥要有"虚拟地址空间"?
目的是为了一定程度的减小内存访问越界,带来的后果
假设进程1 的内存范围是 0x100 - 0x800.
此时我的代码尝试修改 0x801的地址的数据,这操作就是越界访问(错误的操作)
如果这个一个真实的物理地址,就会真的把 0x801 的数据给改了,就可能会影响到其他进程(因为这个内存空间本来是要给其他进程使用的)
如果进程访问的是虚拟地址,进程1 尝试 越界访问,修改 0x801 的数据,此时系统回显针对 0x801来查询页面,在页表中查不到,系统就知道这是越界访问,于是就直接让这个进程出现崩溃(系统会给进程发送一个 SEGMENT_FAULT信号,这个信号通常会导致进程崩溃,防止影响到其他进程)
**这样,就让进程和进程之间相互影响到的可能性变小了,隔离性增加了,进程也就更稳定了.
缺点是当两个进程需要相互配合的时候,沟通起来就困难了(进程间通信)**