计组--操作系统底层原理

汇编语言(机器语言)的执行过程

汇编语言的本质: 机器语言的助记符 其实它就是机器语言

计算机通电->CPU读取内存中程序(电信号输入)->时钟发生器不断震荡通电->推动CPU内部一步一步执行

(执行多少次取决于指令需要的时钟周期)->计算完成->写回(电信号)->写给显卡输出(sout,或者图形)

计算机的组成

pc(程序计数器,记录当前指令地址): 存储的是内存中程序下一条指令的地址,从内存中取指令,如果是数据,存储在寄存器中

Registers(寄存器): 暂时存储CPU计算需要用到的数据

ALU(算术逻辑运算单元): 逻辑运算单元

CU->control unit: 控制单元

MMU->memory management Unit 内存管理单元

通过PC的值,找到对应的指令,通过总线把这条指令拿到CPU中,发现还需要数据,就把数据从内存中拿进来存储在CPU的Registers中来做计算,ALU运算单元才开始运行,运算完将结果写回到内存中去

cache

超线程:一个核有两对PC和Registers

合并写技术:在寄存器与L1之间有一个只有4个字节的WCBuffer,WCBuffer写满以后一次性写入内存

用的缓存一致性协议来保持缓存行中数据一致

对于伪共享

jdk7多用缓存行对齐来提高效率

jdk8,加入了@Contended注解,需要加上: JVM -XX:-RestrictContended

乱序执行

CPU的乱序执行

CPU层面如何禁止指令重排

内存屏障: 对某部分内存做操作时,前后添加的屏障,屏障前后的操作不可以乱序执行

Intel的lfence mfence sfence原语, 也可以使用总线锁来解决

有序性保证, X86CPU内存屏障

sfence: 在sfence指令前的写操作应当必须在sfence指令后的写操作前完成

lfence: 在lfence指令前的读操作应当必须在lfence指令后的读操作前完成

mfence: 在mfence指令前的读写操作应当必须在mfence指令后的读写操作前完成

有序性保证, Intel lock汇编指令

原子指令,如x86上的"lock ..."指令是一个Full Barrier,执行时会锁住内存子系统来确保执行顺序,甚至跨多个CPU.Software Locks通常使用了内存屏障或原子指令来实现变量可见性和保持程序顺序

JVM层面如何禁止指令重排

JVM层级  JSR内存屏障

LoadLoad屏障: 上面一条Load指令,下面一条Load指令,这两条Load指令不可互换,下面一样

StoreStore屏障

LoadStore屏障

StoreLoad屏障

happens-before原则(JVM规定重排序必须遵守的规则)

就是规定在哪种情况下不能重排序

as if serial

不管如何重排序,单线程执行结果不会改变,看上去像是serial

volatile的实现细节 JVM层面

StoreStoreBarrier          LoadLoadBarrier

volatile 写操作               volatile 读操作

StoreLoadBarrier           LoadStoreBarrier

WC - Write Combining  合并写技术

为了提高写效率: CPU在写入L1时,同时用WC写入L2

一般是四个字节

由于ALU速度太快,所以在写入L1的同时,写入一个WC Buffer,满了之后,再直接更新到L2

UMA和NUMA

UMA: 统一内存访问

缺点: 不易扩展

CPU数量增多后引起内存访问冲突加剧

CPU的很多资源花在争抢内存地址上

4颗CPU比较合适

NUMA: 对于自己插槽上的内存是有优先级的

在我的主板插槽上,一组CPU和内存放在一起的,有自己的专属内存

他们之前是通过总线相连接的,访问其他内存也是没有问题的,通过总线去访问就可以了

ZGC的NUMA Aware

分配内存会优先分配该线程所在CPU的最近内存

在分配内存的时候,优先在当前线程所在CPU组的内存进行分配,可以显著提高效率

操作系统的启动

通电->BIOS uefi工作->自检->到硬盘固定位置加载BootLoader->读取可配置信息->CMOS

内核分类

宏内核 - PC phone

微内核 -弹性部署 5G loT

外核 -科研 实验中 为应用定制操作系统(多租户 request-base GC JVM)

VMM 硬件资源过剩

用户态与内核态

CPU分不同的指令级别

Linux内核跑在ring 0级,用户程序跑在ring3,对于系统的关键访问,需要经过kernel的同意,保证系统健壮性

内核执行的操作 -> 200多个系统调用 sendfile read write pthread fork

JVM -> 站在OS的角度,就是个普通程序

进程 线程 纤程

进程和线程有什么区别?

进程是一个程序运行起来的状态,线程是一个进程中不同的执行路径.专业:进程是OS分配资源的基本单位,线程是执行调度的基本单位.分配资源最重要的是:独立的内存空间,线程调度执行(线程共享进程的内存空间)

进程

Linux中也称为task,是系统分配资源的基本单位

资源:独立的地址空间 内核数据结构 (进程描述符...) 全局变量 数据段...

进程描述符: PCB(Process Control Block)

线程

线程在Linux中的实现:就是一个普通进程,只不过和其他进程共享资源(内存空间 全局数据等...)

其他系统都有各自的所谓LWP的实现 Light Weight Process

高层面理解: 一个进程中不同的执行路径

纤程或协程

用户态的线程,线程中的线程,切换和调度不需要经过OS

优势: 1.占用资源很少 OS:线程1M Fiber 4k

2.:切换比较简单

3:启动很多歌10W+

纤程的应用场景

纤程VS线程池: 很短的计算任务,不需要和内核打交道,并发量高!

内核线程

内核启动之后经常需要做一些后台操作,这些由Kernal Thread来完成,只在内核空间运行

进程的创建和启动

系统函数fork() exec() 从A中fork B的话,A称为B的父进程,fork()函数内部调用clone()函数

僵尸进程

ps -ef | grep defuct

父进程产生子进程之后,会维护子进程的一个PCB结构,子进程退出,由父进程释放

如果父进程没有释放,那么子进程成为一个僵尸进程

孤儿进程

子进程结束之前,父进程已经退出

孤儿进程会成为init进程的孩子,由1号进程维护

进程调度

内核进程调度器决定:该哪一个进程运行?何时开始?运行多长时间?

多任务

非抢占式(cooperative multitasking)

除非进程主动让出CPU(yielding),否则将一直运行

抢占式(preemptive multitasking)

由进程调度器强制开始或暂停(抢占)某一进程的执行

Linux采用的调度策略

Linux2.5  经典Unix O(1)调度策略,偏向服务器,但对交互不友好

Linux2.6.23  采用CFS完全公平调度算法Completely Fair Scheduler

CFS调度算法

按优先级分配时间片的比例,记录每个进程的执行时间,如果有一个进程执行时间不到它应该分配的比例,优先执行

进程调度基本概念

进程类型

IO密集型 大部分时间用于等待IO

CPU密集型 大部分时间用于闷头计算

进程优先级

实时进程 > 普通进程 (0-99)

普通进程nice值 (-20-99)

时间分配

Linux采用按优先级的CPU时间比

其他系统多采用按优先级的时间片

Linux默认的调度策略

实时(急诊): 优先级分高低-FIFO,优先级一样 --RR(轮询)

普通: CFS

对于实时进程: 使用SCHED_FIFO和SCHED_RR两种

对于普通进程: 使用CFS

其中等级最高的是FIFO,这种进程除非自己让出CPU,否则Linux会一直执行它,除非更高级别的FIFO和RR抢占它

RR只是这种线程中同级别FIFO中的平均分配

只有实时进程主动让出,或者执行完毕后,普通进程才有机会运行

中断

硬件中断(硬中断)

在键盘上按下了任意一个键,它会找到中断控制器,中断控制器发现有一个信号传了过来;这个中断控制器会告诉CPU,CPU有一个针脚就是专门接受中断信号的

先判断是哪种类型的中断,然后去查这个中断向量表中的处理程序是的哪一个

CPU到内存的固定位置去找处理程序,由操作系统管理

来了一个信号,交给内核,找到对应的中断处理程序,然后开始处理

硬中断完整流程

按下一个键信号之后,会交给中断处理器,中断处理器会通知CPU说有一个键盘信号来了,而CPU会到某个一固定位置,找到执行程序,这个执行程序会通知内核,说有一个中断信号来了,

内核会根据中断信号找到已经写好的一堆中断处理程序;

内部处理完成后,我自己会直到有哪些程序正在运行着,比如说那个程序在最前排,比如说这个office它在等在着一个键盘的输入,

内核就会把这个信号传递给这个office,然后由这个office对这个中断信号进行处理

软中断(0x80中断)

要调用系统函数的时候触发

软中断详细过程

系统调用: int 0x80或sysenter原语,通过ax寄存器填入调用号

参数通过bx cx dx si di传入内核,返回值通过ax返回

java读网路-jvm read()-c库read()->内核空间->system_call() (系统调用处理程序)->sys_read()

内存管理

内存管理的发展历程

DOS时代-同一时间只能有一个进程在运行(也有一些特殊算法可以支持多进程)

Windows9x-多个进程装入内存

早期系统:多个进程全部装入内存,出现两个问题

1.内存撑爆

2.互相打扰 不小心访问到别人的空间

为了解决这两个问题,诞生了现在的内存管理系统:

现代内存管理系统

虚拟地址 分页装入 软硬件结合 寻址

解决内存撑爆问题: 分块儿装入页框中(内存页 4K标准页)(局部性原理: 时间局部性-指令旁边的指令很快执行  空间局部性-数据旁边的数据很快用到)内存满了,进行交换分区(LRU算法)

1. 分页(解决内存不够用),内存中分成固定大小的页框(4K),把程序(磁盘上)分成4K大小的块,用到哪一块,加载哪一块,加载的过程中,如果内存已经满了,会把最不常用的一块放到swap分区,把最新的一块加载进来,这就是著名的LRU

2. 虚拟内存(解决相互打扰问题)

每一个进程都虚拟的独占整个CPU,进程内部分段,段内部分页,需要该页的时候加载到页框

为了保证互不影响-让进程工作在虚拟空间,程序中用到的空间地址不再是直接的物理地址,而是虚拟的地址,这样,A进程永远不可能访问到B进程的空间

虚拟空间多大呢?寻址空间-64位系统 2^64byte,比物理空间大很多

站在虚拟的角度,进程是独享整个系统 + CPU

内存映射:偏移量 + 段的基地址 = 线性地址 (虚拟空间)

线性地址通过 OS + MMU(硬件 Memory Management Unit)映射到物理地址

3. 缺页中断(不是很重要)

需要用到页面内存中没有,产生缺页异常(中断),由内核处理并加载

ZGC

算法叫做:Colored Pointer

GC信息记录在指针上,不是记录在头部, immediate memory use

42位指针 寻址空间4T JDK13 -> 16T 目前为止最大16T 2^44

CPU如何区分一个立即数 和 一条指令

总线内部分为:数据总线 地址总线 控制总线

地址总线目前:48位

颜色指针本质上包含了地址映射的概念

内核同步机制

关于同步理论的一些基本概念

•临界区(critical area): 访问或操作共享数据的代码段 简单理解:synchronized大括号中部分(原子性)

•竞争条件(race conditions)两个线程同时拥有临界区的执行权

•数据不一致:data unconsistency 由竞争条件引起的数据破坏

•同步(synchronization)避免race conditions

•锁:完成同步的手段(门锁,门后是临界区,只允许一个线程存在) 上锁解锁必须具备原子性

•原子性(象原子一样不可分割的操作)

•有序性(禁止指令重排)

•可见性(一个线程内的修改,另一个线程可见)

互斥锁 排他锁 共享锁 分段锁

内核同步常用方法

1.原子操作 – 内核中类似于AtomicXXX,位于<linux/types.h>

2.自旋锁 – 内核中通过汇编支持的cas,位于<asm/spinlock.h>

3.读-写自旋 – 类似于ReadWriteLock,可同时读,只能一个写 读的时候是共享锁,写的时候是排他锁

4.信号量 – 类似于Semaphore(PV操作 down up操作 占有和释放) 重量级锁,线程会进入wait,适合长时间持有的锁情况

5.读-写信号量 – downread upread downwrite upwrite (多个写,可以分段写,比较少用)(分段锁)

6.互斥体(mutex) – 特殊的信号量(二值信号量)

7.完成变量 – 特殊的信号量(A发出信号给B,B等待在完成变量上) vfork() 在子进程结束时通过完成变量叫醒父进程 类似于(Latch)

8.BKL:大内核锁(早期,现在已经不用)

9.顺序锁(2.6): – 线程可以挂起的读写自旋锁 序列计数器(从0开始,写时增加(+1),写完释放(+1),读前发现单数, 说明有写线程,等待,读前读后序列一样,说明没有写线程打断)

10.禁止抢占 – preempt_disable()

11.内存屏障 – 见volatile

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值