目录
2. PCB——进程控制块抽象(Process Control Block)

CPU 中央处理器(center process unit): 进行算术运算和逻辑判断.(ALU+CU+寄存器+时钟)
存储器: 分为外存和内存, 用于存储数据(使用二进制方式存储)
输入设备: 用户给计算机发号施令的设备:网卡,手写笔
输出设备: 计算机个用户汇报结果的设备.
针对存储空间
硬盘 > 内存 >> CPU
针对数据访问速度
CPU >> 内存 > 硬盘
程序=指令+数据 / CPU=ALU+CU
ALU(算数逻辑单元):CPU的执行单元,是所有中央处理器的核心组成部分,由“与门”和“或门”构成,算术逻辑单元的运算主要是进行二位元算术运算,如加法、减法、乘法。
CU(控制单元):负责程序的流程管理
1.取指令
即将一条指令从主存储器中取到的指令寄存器过程。
2.指令译码阶段
取出指令后,指令译码器按照预定的指令格式,对取回的指令进行拆分和解释,识别区分出不同的指令类别以及各种获取操作数的方法。
3.执行指令阶段
具体实现指令的功能。CPU的不同部分被连接起来,以执行所需的操作。
4.访存取数阶段
根据指令需要访问主存、读取操作数,CPU得到操作数在主存中的地址,并从主存中读取该操作数用于运算。部分指令不需要访问主存,则可以跳过该阶段。
5.结果写回阶段
作为最后一个阶段,结果写回阶段把执行指令阶段的运行结果数据“写回”到某种存储形式。
在指令执行完毕、结果数据写回之后,若无意外事件(如结果溢出等)发生,计算机就从程序计数器中取得下一条指令地址,开始新一轮的循环,下一个指令周期将顺序取出下一条指令。
1. CPU 中的 PC 寄存器,是决定 CPU 要执行哪条指令的关键;
2. 指令是由 动作 + 操作对象组成
3. CPU 眼中只有指令,没有其他的概念
简单来说,可以把进程看做程序的一次运行过程;
同时,在操作系统内部,进程又是操作系统进行资源分配的基本单位。
每一个PCB对象,就代表一个正在运行的程序,即进程 ,其包含
一个主机,同一时刻,这些进程的pid是唯一的,通过pid来区分一个进程
一个可执行文件,双击运行后,操作系统把文件中的核心数据加载到内存中
内存空间分配:存放指令+存放数据+维护运行状态
用于记录当前进程中打开的文件
创建一个进程,本质上就是创建PCB,并且加入到链表上
1.创建PCB
2.给进程分配资源(内存/文件),赋值到PCB中
3.把PCB插入到链表中
销毁一个进程,本质上就是从链表是删除对应的PCB节点
1.把PCB从链表上删除
2.
分为就绪和阻塞,一旦进程阻塞,则无法被调度到CPU上执行
系统调用的时候,就会根据优先级,来给进程进行安排时间,当创建进程的时候,可以通过一些系统调用来干预优先级
相当于存档与读档,即将运行中的值存储在CPU的寄存器中,下次在由此进行
记录每个进程在CPU上执行了多久,统计信息
并行:某一个时刻,多个程序同时运行
并发:某一个CPU, cpu来回切换多个程序
但对于肉眼来说,无法看出差别
虚拟地址空间会给每个进程安排一些内存资源,通过专门的设备MMU来完成虚拟地址到物理地址之间的映射,增加了隔离性,使进程稳定
添加一个多个进程都能访问到的公共资源,然后基于公共资源来交换数据,使得进程间进行交互
使用多线程:
1.能够充分利用上多核CPU,能够提高效率
2.创建第一个线程的时候,需要申请资源,后续再创建新的进程,都是共用同一份资源
(节省了申请资源的开销)
销毁线程的时候,也是销毁到最后一个的时候,才真正释放资源
1.进程是资源分配的基本单位 ,线程是调度执行的基本单位
2.进程包含线程
3.线程比进程更轻量,创建快,销毁也快
4.同一个进程的多个线程之间共用同一份内存/文件资源 ,而进程与进程间是独立的
1) 继承 Thread 来创建一个线程类.
class MyThread extends Thread {
@Override
public void run() {
System.out.println("这里是线程运行的代码");
}try{
Thread.sleep(1000);//休眠1000ms.即1s
} catch(InterruptedException){
e.printStackTrace();
}
}
2) 创建 MyThread 类的实例
MyThread t = new MyThread();//非进程
3) 调用 start 方法启动线程
t.start();//创建实例并不会产生进程,使用后才会产生
抢占式执行:当启动另外一个线程,新的线程是一个单独的执行流,和现有线程的执行流不相关,并发+并行执行,但是操作系统调度现成的时候是一个“随机”的过程,所以执行的时候也会产生随机
1) 实现 Runnable 接口
class MyRunnable implements Runnable{
public void run(){
System.out.println("这里是线程运行的代码");
try{
Thread.sleep(1000);//休眠1000ms.即1s
} catch(InterruptedException){
e.printStackTrace();
}
}
}
2) 创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.
Thread t = new Thread(new MyRunnable());
3) 调用 start 方法
t.start();
1.把任务从线程提取出来,把线程要干的活和线程本身分开了
2.如果要搞多个线程干相同的事情,
Thread t1 = new Thread() {
@Override
public void run() {
System.out.println("使用匿名类创建 Thread 子类对象");
}
};
Thread t2 = new Thread(
new Runnable() {
@Override
public void run() {
System.out.println("使用匿名类创建 Runnable 子类对象");
}
});
Thread t3 = new Thread(
() -> System.out.println("使用匿名类创建 Thread 子类对象")
);
Thread t4 = new Thread(() -> {
System.out.println("使用匿名类创建 Thread 子类对象");
});
覆写 run 方法是提供给线程要做的事情的指令清单
而调用 start 方法, 才真的在操作系统的底层创建出一个线程.
t1.join();
t2.join();
此处t1和t2是并发执行,而不是t1执行完后才继续执行