java开发硬件_Java开发者需要了解的硬件知识(⼆)、操作
系统篇
前⾔:
上⼀篇讲了CPU,作为整个计算机的核⼼计算硬件,讲解了它于JAVA语⾔间的⽠葛。这⼀篇讲讲计算机软件⾥的⽼⼤哥OS ----操作系统。
因为学习内容⾥有些不那么重要的知识点,往往就是截图或者少量⽂字带过,个⼈笔记不会记录那么多细节,详细资料请读者⾃⼰查询,见谅。
正⽂:
计算机的启动过程
通电 -> bios uefi ⼯作 -> ⾃检 -> 到硬盘固定位置加载bootloader -> 读取可配置信息 -> CMOS
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分配资源的基本单位,线程是执⾏调度的基本单位。
进程最重要的分配资源是:独⽴的内存空间,线程调度执⾏(线程共享进程的内存空间,没有⾃⼰独⽴的内存空间)
进程
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()
java学习资源
内存管理
DOS时代 - 同⼀时间只能有⼀个进程在运⾏(也有⼀些特殊算法可以⽀持多进程)
windows9x - 多个进程装⼊内存,如此就会出现两个问题
内存不够⽤
互相打扰
为了解决这两个问题,诞⽣了现在的内存管理系统:虚拟地址 分页装⼊ 软硬件结合寻址
分页(内存不够⽤),内存中分成固定⼤⼩的页框(4K),把程序(硬盘上)分成4K⼤⼩的块,⽤到哪⼀块,加载那⼀块,加载的过程中,如果内存已经满了,会把最不常⽤的⼀块放到swap分区(即交换区,系统运⾏内存不够时,与Swap进⾏交换), 把最新的⼀块加载进来,这个就是著名的LRU算法
LRU算法 LeetCode146题Least Recently Used 算法(翻译为最不常⽤)
哈希表(保证 查操作复杂度为O(1)) + 链表 (保证 排序操作和新增操作复杂度为 O(1)))
双向链表 (保证查效率)
虚拟内存(解决相互打扰问题)
DOS Win31 ... 这些旧的系统,都会直接操作内存,可能导致进程间互相⼲掉对⽅
为了保证互不影响 - 让进程⼯作在虚拟空间,程序中⽤到的空间地址不再是直接的物理地址,⽽是虚拟的地址,这样,A进程永远不可能访问到B进程的空间
虚拟空间多⼤呢?寻址空间 - 64位系统 2 ^ 64,⽐物理空间⼤很多 ,单位是byte
站在虚拟的⾓度,进程是独享整个系统 + CPU
内存映射:偏移量 + 段的基地址 = 线性地址 (虚拟空间)
线性地址通过 OS + MMU(硬件 Memory Management Unit),得到对应的物理内存地址
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论