大家好,又见面了,我是你们的朋友全栈君。
1、用户态和内核态的区别?
明白这两个概念之前,我们得知道用户空间和内核空间。
用户空间:指的就是用户可以操作和访问的空间,这个空间通常存放我们用户自己写的数据等。
内核空间:是系统内核来操作的一块空间,这块空间里面存放系统内核的函数、接口等。
在用户空间下执行,我们把此时运行得程序的这种状态成为用户态,而当这段程序执行在内核的空间执行时,这种状态称为内核态。
当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核状态。此时处理器处于特权级最高的(0级)内核代码。当进程处于内核态时,执行的内核代码会使用当前的内核栈。每个进程都有自己的内核栈。
当进程在执行用户自己的代码时,则称其处于用户态。即此时处理器在特权级最低的用户代码中运行。当正在执行用户程序而突然中断时,此时用户程序也可以象征性地处于进程的内核态。因为中断处理程序将使用当前进程的内核态。
延伸阅读:内核态与用户态是操作系统的两种运行级别,跟intel cpu没有必然联系,intel cpu提供Ring0-Ring3三种级别运行模式,Ring0级别最高,Ring3级别最低。Linux使用了Ring3级别运行用户态。Ring0作为内核态,没有使用Ring1和Ring2.Ring3不能访问Ring0的地址空间,包括代码和数量。Linux进程的4GB空间,3G-4G这1G部分大家是共享的,是内核态的地址空间,这里存放在整个内核代码和所有的内核模块,以及内核所维护的数据。用户运行一程序,该程序所创建的进程开始是运行在用户态的,如果要执行文件操作,网络数据发送等操作,必须通过write,send等系统调用,这些系统会调用内核中的代码来完成操作,这时,必须切换到Ring0,然后进入1G的内核地址空间去执行这些代码完成操作,完成后,切换Ring3,回到用户态。这样,用户态的程序就不能随意操作内核地址空间,具有一定的安全保护作用。
2、用户态和内核态的转换
用户态切换到内核态的3种方式:a.系统调用 b.异常 c.外围设备的中断
a.系统调用
这是用户进程主动要求切换到内核态的一种方式,用户进程通过系统调用申请操作系统提供的服务程序完成工作。
而系统调用的机制其核心还是使用了操作系统为用户特别开放的一个中断来实现,该中断是程序人员自己开发出的一种正常的异常,这个异常具体就是调用int $0x80的汇编指令,这条汇编指令将产生向量为0x80的编程异常。(软中断)
b.异常 当CPU在执行运行在用户态的程序时,发现了某些事件不可知的异常,这是会触发由当前运行进程切换到处理此 异常的内核相关程序中,也就到了内核态,比如缺页异常(硬中断)。
c.外围设备的中断 当外围设备完成用户请求的操作之后,会向CPU发出相应的中断信号,这时CPU会暂停执行下一条将要执行的指令 转而去执行中断信号的处理程序,如果先执行的指令是用户态下的程序,那么这个转换的过程自然也就发生了有 用户态到内核态的切换。比如硬盘读写操作完成,系统会切换到硬盘读写的中断处理程序中执行后续操作等。
以系统调用函数open为例:简单图示
(1)用户态:
① 触发0x80中断
②保存当前的运行位置,状态,数据
③将系统调用号保存到eax寄存器中
触发0x80中断 由系统调用函数触发的中断 。实际上在内核中, 触发0x80中断之后才会有上面的两步 。
(2)每一个中断号在内核中都有一个中断处理程序,中断处理程序是被内核调用来响应中断的
通过该中断处理程序陷入内核
(3)在内核中:①有系统调用表,用寄存器中的系统调用号对应一个系统调用函数
②通过函数得到执行该系统调用函数会得到一个返回值fd
③将fd的值用eax寄存器带出
在函数调用时int fd=open();open调用完之后才会将eax中的得到的返回值赋给fd,相当于是两个步骤
只有0x80中断才是系统调用中断,类似的还有缺页中断它们所对应的中断号是不同的
注释:在c语言中如何返回返回值:如果返回值小于四个字节通过eax寄存器带出 若在4-8之间用eax和ecx带出 大于8通过生成临时对象或者变量带出
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/192248.html原文链接:https://javaforall.cn