posts - 89,comments - 0,views - 12532

用户空间和内核空间

我们这里简单解释下这两个概念,我们平时的编程就是在用户空间去做的,然后内核空间一般是操作系统的地盘,主要就是和硬件打交道,控制资源分配等,它受到一些特定的保护,我们不能随意闯入

可以注意下,就是 用户空间的级别是比内核空间的级别低 的,换句话说,内核空间里的是老大,我们想要做一些与 硬件 打交道的就必须得经过内核的同意,比如说输出字符串到屏幕上,屏幕就算是硬件,还有读取文件,这是磁盘IO,磁盘也是硬件,这些都是要经过内核同意的

清楚了这两个概念后,你可能会疑惑那要怎么得到内核的同意呢,答案就是系统调用,系统调用就相当于是内核空间和用户空间的桥梁,系统调用可以看成是函数吧,用户空间把用到的参数传递给系统调用,然后在通过系统调用传递给内核,最后执行结果

当然平时我们使用的是库函数,系统调用已经被封装好了,我们不用知道,所以有些库函数也可以叫做 外壳函数,意思就是对系统调用进行了包裹

比如说 printf 这个C语言库函数,它的内部实际上调用了系统调用 write 函数,不过库函数会提供更丰富的功能就是了

系统调用的流程

1

上面是一个例子,用户态其实就是用户空间,内核态就是内核空间

让我们解析下这个系统调用 execve 的执行步骤,我们不必关心它的作用是什么

首先,我们在 用户空间应用程序 调用了 execve 函数,我们这里传入了三个参数 path, argv, envp, 然后进入 execve 函数的内部,也就是外壳函数的内部

然后就一直往下执行,遇到 int 0x80 这条指令,这条指令的意思就是 引发中断,你可以把它看成是 我要进入内核空间 的意思,然后我们可以看到这里进入内核空间前,传入的参数是4个,比我们在 应用程序 中传入的多了一个 __NR__execve ,这多出来的一个就是标识execve函数的 中断号,你可以理解为函数名( 这很好理解,系统调用其实也相当于是函数,他们在内核空间中也有属于自己的代码,所以中断号其实就和函数名差不多,是为了区分和方便调用 )

再然后,经过一些检查,我们成功进入了内核空间,进入到的是 中断处理程序,其实就是系统调用的具体代码的入口啦,然后根据我们的 中断号 跳转到具体的代码中执行,最后执行完后,在一路返回到用户空间中

以上就是系统调用的大致流程了

补充

这里先给出书上的一段话

系统调用允许进程向内核请求服务。与用户空间的函数调用相比,哪怕是最简单的系统调用都会产生显著的开销,其原因是为了执行系统调用,系统需要临时性地切换到核心态,此外,内核还需验证系统调用的参数、用户内存和内核内存之间也有数据需要传递

我在这里给出我的理解,系统调用会产生显著的开销,主要是因为系统临时性的切换到内核态,这个切换涉及到CPU中的一些寄存器,比如CS、SS、DS等等,具体的功能大家就自行查阅了,我想说的是,当你进行内核态和用户态的切换时,这些寄存器的值也要进行改变(先保存旧值,然后赋新值),因为CPU就只认得这些寄存器,所以要让CPU切换到内核去执行,就必须让这些寄存器指向内核空间,然后切换的过程中还需要检查传入的参数,数据的传递等等,最后还要从内核态回到用户态

对比下用户空间的函数调用,他们是在同一层级,所以也就不需要进行这种复杂的切换

总之,不同层级的切换一般是比同层级的切换复杂的,所以开销也大一点

posted on   Dylaris  阅读(73)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示