首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Linux内核空间和用户空间

Linux内核空间和用户空间
EN

Stack Overflow用户
提问于 2013-06-20 08:21:06
回答 2查看 10.6K关注 0票数 12

我不知道内核和用户空间究竟是如何构造的,以及占用的内存的哪些部分。我目前(可能错了)的理解是:

  1. 创建一个进程,该进程的虚拟内存被划分为用户空间和内核空间区域,其中用户空间区域包含进程的数据、代码、堆栈、堆等,内核空间区域包含进程的页表和内核代码。我不确定be...driver代码或类似的内核代码会是什么?
  2. 另外,系统调用表是否总是映射到进程内核空间中的同一区域?(说“进程的内核空间”是正确的吗?
  3. 如果我编写自己的驱动程序/模块并插入它,那么该驱动程序代码会自动复制到创建的每个新进程的内核空间中吗?如果not...how正是这样做的话?

预先感谢您的任何投入,可以帮助澄清我的问题的文献/链接也可以。

干杯,布里克

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-06-21 03:16:03

大致上,您的想法是正确的,但是调整一下:整个机器只有一个“内核空间”,所有进程都共享它。

当进程处于活动状态时,它既可以以“用户模式”运行,也可以以“内核模式”运行。

在用户模式下,CPU执行的指令位于内存映射的用户空间一侧。该程序正在运行自己的代码,或者是来自用户空间库的代码。在用户模式下,进程的能力有限。CPU中有一个标志告诉它不允许使用特权指令,内核内存虽然存在于进程的内存映射中,但是不可访问的。(您不想让任何程序只读和写内核的内存-所有的安全性都会消失。)

当一个进程想要在它自己的(用户空间)虚拟内存中移动数据以外的其他事情时,比如打开一个文件,它必须创建一个syscall。每个CPU架构都有自己独特的制作syscalls的奇特方法,但它们都归结为:执行神奇指令,CPU打开“特权模式”标志,跳转到内核空间中的一个特殊地址,即"syscall入口点“。

现在进程在内核模式下运行。正在执行的指令位于内核内存中,它们可以读取和写入任何他们想要的内存。内核检查进程刚刚发出的请求,并决定如何处理它。

open示例中,内核接收对应于int open(const char *filename, int flags[, int mode])参数的2或3个参数。第一个参数提供了内核空间何时需要访问用户空间的示例。您说的是open("foo", O_RDONLY),所以字符串"foo"是用户空间中程序的一部分。syscall机制只传递一个指针,而不是字符串,因此内核必须从用户内存中读取字符串。

要查找所请求的文件,内核可以咨询文件系统驱动程序(以确定文件位于何处)和阻塞设备驱动程序(从磁盘加载必要的块)或网络设备驱动程序和协议(从远程源加载文件)。所有这些东西都是内核的一部分,即内核空间,不管它们是内置的还是作为模块加载的。

如果请求不能立即满足,内核可能会使进程处于休眠状态。这意味着进程将从CPU中取出,直到从磁盘或网络接收到响应为止。另一个进程现在可能有机会运行。稍后,当响应出现时,您的进程将再次开始运行(仍然处于内核模式)。找到文件后,open系统调用就可以完成(检查权限、创建文件描述符)并返回到用户空间。

返回到用户空间是一个简单的问题,将CPU恢复到非特权模式,并将寄存器恢复到用户->内核转换之前的状态,指令指针指向神奇的syscall指令之后的指令。

除了syscalls之外,还有其他事情可能导致从用户模式到内核模式的转换,包括:

  1. 页面错误-如果您的进程访问一个没有物理地址分配给它的虚拟内存地址,CPU进入内核模式并跳转到页面错误处理程序。然后内核决定虚拟地址是否有效,它要么创建一个物理页面,然后在进程中断的用户空间中继续运行,要么发送一个SIGSEGV。
  2. 中断-一些硬件(网络、磁盘、串口等)通知CPU它需要注意。CPU进入内核模式并跳转到处理程序,内核响应它,然后恢复中断之前运行的用户空间进程。

加载模块是使用syscall完成的,它要求内核将模块的代码和数据复制到内核空间,并在内核模式下运行其初始化代码。

太长了,所以我停下来。我希望专注于用户内核转换的演练提供了足够的例子来巩固这一想法。

票数 34
EN

Stack Overflow用户

发布于 2013-06-20 20:36:01

在进程的虚拟内存映射中没有内核空间区域。虚拟内存映射有:文本、bss、数据、堆、加载程序的堆栈和共享库。在Linux上,您可以检查/proc/$PID/映射任何用户空间进程作为示例。

当用户空间进程通过系统调用访问某些内核域代码时,内核代码将代表其堆栈中的进程执行。显然,从系统调用返回后,所有内核/驱动程序代码都将退出堆栈。为了进一步澄清,如果某一时刻内核代码的某些部分没有被任何进程使用,它将不会是任何进程的虚拟内存映射的一部分。

如果您正在使用Linux,我推荐Robert的"Linux内核开发“一书。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17208648

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档