用户态和内核态

用户态:用户代码和数据被访问或者执行的时候,所处的状态

内核态:执行OS的代码和数据时,计算机所处的状态就叫内核态

两者最大的区别就在于权限,以printf函数为例,该函数的本质其实是向加载到内存即内核中的stdout文件写入数据,此时我们要从用户层进入内核,必须要从用户态转变成内核态,权限会扩大!下面就以printf函数的运行为例,来介绍用户态和内核态


目录

一、进程为什么能使用OS的代码??

二、用户态和内核态的相互切换


一、进程为什么能使用OS的代码??

进程运行自己的代码,只需要循着 用户区虚拟地址——》页表——》物理内存 这条路线就能找到对应的代码和数据,但是进程是如何找到OS的代码呢?

介绍虚拟地址空间的时候有这么一张图,用户代码放在代码区,也就是用户空间的那3G中,最上面还有1G的内核空间,没错,这里就存放着OS的代码!!

访问内核空间的方式和访问用户空间一样,也是通过页表访问,但是所有的进程使用的都是同一份内核代码,并不会因为进程的代码发生变化 ——》 内核空间的页表也就只有一份!!

所以我们在进行系统调用的时候,实际上是走的内核空间 ——》 内核空间的页表 ——》物理内存 这条路线

注意像磁盘驱动函数,类似于这种我们看不到的函数,都是OS的代码,OS的代码早在开机运行的时候就被加载到内存了

二、用户态和内核态的相互切换

下面就以具体例子来分析,我们用户层要运行的代码如下

//test.c
int main()
{
    printf("hello,world!\n");
    return 0;
}

当上述代码被加载到内存时,对应的进程就会被创建。现在把进程加入到CPU运行队列中,CPU中有一个寄存器CR3,这个寄存器记录着当前进程的状态。CR3 = 0,表示当前状态是内核态;CR3 = 3,表示当前状态是用户态。

此时就会循着用户空间中的地址找到进程A的代码,运行prinft语句,此时是访问用户层的代码,处在用户态(CR3 = 3)

由于printf实际上是向stdout文件写入数据,所以必须要使用系统调用进入内核,此时需要切换成内核态(CR3 = 0),然后去执行OS的代码,至于如何找到内核代码,第一部分已经说过了

等到执行完内核代码,即向stdout文件中写入数据,就会返回到用户态(CR3 = 3),因为原本的代码还没有执行完,即继续执行printf 的下一句return 0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值