一。前言 想起很多年前被问到了用户态和内核态的相关问题,当时一知半解,但是工作这么些年,也极少听到这个概念,直到最近碰到后,终于决定以Java的角度,真正的了解一下这2个状态的实际作用。二。内核态的概念和本质2。1概念与体现 内核主要控制计算机的硬件资源,并且提供运行环境给上层应用程序。概念:态是一种操作系统的运行级别。内核态通常是管理程序运行的状态,具有更高的级别,在这个状态可以执行所有的指令,以及使用所有的资源用户态通常是用户应用的运行状态,权限较低,不可以使用特权指令,也不能直接使用系统资源,只能访问各自的存储空间行为:内核可以控制计算机的硬件资源,并且提供应用程序的运行环境通过内核态调用内核的核心资源原因:权限的管理:避免高危指令执行出现问题,引发系统崩溃。高风险指令只能有限的开发给用户。避免资源消耗:系统资源是有限的,要减少访问系统资源的操作,避免过多的消耗场地:CPU执行用户态和内核态指令,标识着当前CPU的运行态(运行级别) 其他基础概念:系统调用:内核为上层应用提供访问的接口,用于访问内核中的资源系统调用是操作系统的最小功能资源库函数:是对系统调用的封装,再通过简单的接口呈现给用户Shell:特殊的应用程序,可以通过Shell命令方便的进行系统调用,并且可以集成到编程体系中 区别和对比超级管理员与内核态的区别:超级管理员是特殊的计算机用户,主要是软件层面的一种角色。超级管理员不一定在内核态处理业务。2。2内核态和用户态分级 功能区别用户态功能:汇编编译编辑shellAPI函数(读写)内核态功能:进程管理存储管理文件管理设备管理 2。3用户态到内核态的切换场景 用户态内核态系统调用:通过任何途径进行系统调用的时候,都会发生2态的装欢异常事件:当发生一些系统级别的异常事件时,CPU会处理异常事件,从而发生切换外围系统中断:当外围系统完成后,会向CPU发送中断信号,此时CPU开始处理中断信号 内核态用户态设置程序状态字PSW 总结:内核态可以随意切换到用户态。用户态只能通过系统调用和中断来到内核态三。Java中内核态和用户态的涉及情况3。1Java上内核态的使用线程进行上下文切换,堵塞,时间片使用完成,睡眠等操作时,会发生多态和切换线程切换的调度器在内核中线程切换和态切换没有直接关系,但是多数切换都是放在内核中进行3。2多态转换的流程设置处理器至内核态。保存当前寄存器(栈指针、程序计数器、通用寄存器)。将栈指针设置指向内核栈地址。将程序计数器设置为一个事先约定的地址上,该地址上存放的是系统调用处理程序的起始地址。而之后从内核态返回用户态时,又会进行类似的工作。3。2多态切换会有哪些风险 无锁并发编程。多线程竞争锁时,加锁、释放锁会导致比较多的上下文切换CAS算法。使用CAS避免加锁,避免阻塞线程使用最少的线程。避免创建不需要的线程协程。在单线程里实现多任务的调度,并在单线程里维持多个任务间的切换 切换耗时原因: 当发生切换时,第一个操作点就是保存现场,再在另外的态中恢复现场。这种时间消耗不多,但是如果调用非常频繁,耗时累加也是很多的。 第二个操作点时,当切换内核态的时候,内核需要进行额外的校验,检查是否需要调度等,也会占用额外的耗时。四。JVM和Linux关于内核态和用户态的边界4。1底层角度出发 内核栈和内存的隔离堆和栈和Java角度是一致的,在Linux中,进程线程都是通过一个taskstruct的实例描述taskstruct中有一个stack用于保存内核栈地址用户态的堆、栈对应用户进程虚拟地址空间里的一个区域内核通过虚拟地址访问权限来限制用户程序访问内存地址4。2JVM层面分析 空间划分:内核空间:最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF)由内核态使用用户空间:较低的3G字节(从虚拟地址0x00000000到0xBFFFFFFF)由各个进程使用 进程上下文在上下文中,用户进程会将参数传递给内核,同时内核会保存寄存器值和当前环境信息用户级上下文:正文、数据、用户堆栈以及共享存储区寄存器上下文:通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP)系统级上下文:进程控制块taskstruct、内存管理信息(mmstruct、vmareastruct、pgd、pte)、内核栈 PS:这里就存在上下文切换的场景 Java中涉及切换的操作IO操作会直接调用系统硬件线程操作,线程创建切换直接涉及到多个态的转换创建对象等场景的内存分配4。3开发中对内核态和用户态的使用C语言中的sork()来分配内存print()函数会调用wirte()进行系统调用输出字符串申请动态的内存空间总结 看了很多文档,还是感觉一知半解,没有从实践角度弄懂,到底他们在业务中有什么影响。只能说大概了解了其中的组成。