java开发硬件_Java开发者需要了解的硬件知识 (二)、操作系统篇

前言:

上一篇讲了CPU,作为整个计算机的核心计算硬件,讲解了它于JAVA语言间的瓜葛。这一篇讲讲计算机软件里的老大哥OS ----操作系统。

因为学习内容里有些不那么重要的知识点,往往就是截图或者少量文字带过,个人笔记不会记录那么多细节,详细资料请读者自己查询,见谅。

正文:

计算机的启动过程

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

a5fc8f79076e397127e433ddd4725c47.png

OS 操作系统

内核分类

微内核 - 弹性部署 5G IoT

宏内核 - PC phone

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

用户态和内核态

cpu分不同的指令级别

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

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

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

进程 线程 纤程(协程) 中断

面试高频:进程和线程有什么区别?

专业答案:进程是OS分配资源的基本单位,线程是执行调度的基本单位。

进程最重要的分配资源是:独立的内存空间,线程调度执行(线程共享进程的内存空间,没有自己独立的内存空间)

3ad8eb98b31ab5c48889db21324c124c.png

进程

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

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

Linux进程描述符:PCB (Process Control Block),用于Linux的进程管理(线程有他的PCB)

进程在Linux中的创建与启动

调用系统函数 fork()创建进程 ,exec()启动进程

从 A 中fork B 的话,A称之为B的父进程,B称之为A的子进程

僵尸进程

ps -ef |grep defunct (defunct表示无用的僵尸进程)

父进程产生子进程后,会维护子进程的PCB结构,子进程退出后,由父进程释放,如果父进程没有释放,那么子进程会成为一个僵尸进程(defunct)

孤儿进程

子进程结束之前,父进程已经退出,就会产生孤儿进程,孤儿进程会成为Init进程的子进程,由1号进程维护 (在图形化Linux中是1457号线程)

进程调度

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

每个进程都可以自定义不同的调度方案

多任务执行分为

抢占式(大多数现代系统采用):由进程调度器强制开始或暂停(抢占)某一进程的执行

非抢占式:除非进程主动让出(yielding)cpu,否则将一直运行

调度策略

Linux2.6采用CFS调度策略:Completely Fair Scheduler

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

默认调度策略:

实时进程 : 优先级分高低 - FIFO (First In First Out),优先级一样 - RR(Round Robin)

普通:CFS

线程在Linux中的实现

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

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

内核线程

内核启动后需要做一些后台操作,这些操作由Kernel Thread 来完成,它只在内核空间中运行

在JVM中的线程

创建一个JVM中线程,即申请一个操作系统的线程(重量级线程),1:1关系

纤程 Fiber

纤程可以理解为线程里面的线程,用户态的线程而非内核态的线程。

它处于线程内部,非常轻量级,可以在线程中快速切换。JVM自己管理,自己切换,与操作系统无关。

优势:

占有资源很少 ,OS 线程要1M ,而Fiber只需要4K

切换比较简单

可以启动很多个纤程,可以达到10W+

目前2020-03-22支持内置纤程的语言:Kotlin Scala Go Python(lib)...... Java14并没有(open jdk : loom库)

Java中对于纤程的支持:没有内置,盼望内置

纤程的应用场景

纤程 vs 线程池: 纤程适合很短的计算任务, 不需要和内核打交道,并发量高 的场景

中断

硬中断

硬件跟操作系统内核打交道的一种机制

软中断(80中断)

系统调用:int 0x80 或者 sysenter原语

通过ax寄存器填入调用号(调用号指定了对应的内核方法),参数通过bx cx dx si di 寄存器传入内核,最后返回值通过ax返回

java的一个中断例子

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

5de5e7fe369870f50784f1a68285e179.png

内存管理

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

windows9x - 多个进程装入内存,如此就会出现两个问题

内存不够用

互相打扰

为了解决这两个问题,诞生了现在的内存管理系统:虚拟地址 分页装入 软硬件结合寻址

分页(内存不够用),内存中分成固定大小的页框(4K),把程序(硬盘上)分成4K大小的块,用到哪一块,加载那一块,加载的过程中,如果内存已经满了,会把最不常用的一块放到swap分区(即交换区,系统运行内存不够时,与Swap进行交换), 把最新的一块加载进来,这个就是著名的LRU算法

LRU算法 LeetCode146题Least Recently Used 算法(翻译为最不常用)

哈希表(保证 查找操作复杂度为O(1)) + 链表 (保证 排序操作和新增操作复杂度为 O(1)))

双向链表 (保证查找效率)

5465d0843558ff9addb5cd13ca9cc0ba.png

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

DOS Win31 ... 这些旧的系统,都会直接操作内存,可能导致进程间互相干掉对方

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

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

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

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

线性地址通过 OS + MMU(硬件 Memory Management Unit),得到对应的物理内存地址

2fda8d5e9fc05b8f44aeb4af5ffd665b.png

缺页中断(不是很重要):

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

68f724bad5a33d9a9f6bd2ca7369ecb7.png

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值