我不知道内核和用户空间究竟是如何构造的,以及占用的内存的哪些部分。我目前(可能错了)的理解是:
预先感谢您的任何投入,可以帮助澄清我的问题的文献/链接也可以。
干杯,布里克
发布于 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之外,还有其他事情可能导致从用户模式到内核模式的转换,包括:
加载模块是使用syscall完成的,它要求内核将模块的代码和数据复制到内核空间,并在内核模式下运行其初始化代码。
太长了,所以我停下来。我希望专注于用户内核转换的演练提供了足够的例子来巩固这一想法。
发布于 2013-06-20 20:36:01
在进程的虚拟内存映射中没有内核空间区域。虚拟内存映射有:文本、bss、数据、堆、加载程序的堆栈和共享库。在Linux上,您可以检查/proc/$PID/映射任何用户空间进程作为示例。
当用户空间进程通过系统调用访问某些内核域代码时,内核代码将代表其堆栈中的进程执行。显然,从系统调用返回后,所有内核/驱动程序代码都将退出堆栈。为了进一步澄清,如果某一时刻内核代码的某些部分没有被任何进程使用,它将不会是任何进程的虚拟内存映射的一部分。
如果您正在使用Linux,我推荐Robert的"Linux内核开发“一书。
https://stackoverflow.com/questions/17208648
复制相似问题