内核空间, 用户空间; kernel mode/user mode, User space/Kernel space
Contents
内核空间, 用户空间; kernel mode/user mode, User space/Kernel space
User space & Kernel space 现代操作系统会把内存划分为2个区域,分别为Use space(用户空间) 和 Kernel space(内核空间)。用户的程序在User space执行,系统内核在Kernel space中执行。
用户的程序没有权限直接访问硬件资源,但系统内核可以。比如读写本地文件需要访问磁盘,创建socket需要网卡等。因此用户程序想要读写文件,必须要向内核发起读写请求,这个过程叫system call。
内核收到用户程序system call时,负责访问硬件,并把结果返回给程序。
FileInputStream fis = new FileInputStream("/tmp/test.txt”); byte[] buf = new byte[256]; fis.read(buf);
简单说,Kernel space 是 Linux 内核的运行空间,User space 是用户程序的运行空间。为了安全,它们是隔离的,即使用户的程序崩溃了,内核也不受影响。
Kernel space 可以执行任意命令,调用系统的一切资源;User space 只能执行简单的运算,不能直接调用系统资源,必须通过系统接口 (又称 system call) ,才能向内核发出指令。
str = “my string” // 用户空间 x = x + 2 file.write(str) // 切换到内核空间
y = x + 4 // 切换回用户空间 上面代码中,第一行和第二行都是简单的赋值运算,在 User space 执行。第三行需要写入文件,就要切换到 Kernel space,因为用户不能直接写文件,必须通过内核安排。第四行又是赋值运算,就切换回 User space。
查看 CPU 时间在 User space 与 Kernel Space 之间的分配情况,可以使用top命令。它的第三行输出就是 CPU 时间分配统计。 这一行有 8 项统计指标。
其中,第一项24.8 us (user 的缩写) 就是 CPU 消耗在 User space 的时间百分比,第二项0.5 sy (system 的缩写) 是消耗在 Kernel space 的时间百分比。
随便也说一下其他 6 个指标的含义。
ni: niceness 的缩写,CPU 消耗在 nice 进程 (低优先级) 的时间百分比 id: idle 的缩写,CPU 消耗在闲置进程的时间百分比,这个值越低,表示 CPU 越忙 wa: wait 的缩写,CPU 等待外部 I/O 的时间百分比,这段时间 CPU 不能干其他事,但是也没有执行运算,这个值太高就说明外部设备有问题 hi: hardware interrupt 的缩写,CPU 响应硬件中断请求的时间百分比 si: software interrupt 的缩写,CPU 响应软件中断请求的时间百分比 st: stole time 的缩写,该项指标只对虚拟机有效,表示分配给当前虚拟机的 CPU 时间之中,被同一台物理机上的其他虚拟机偷走的时间百分比 如果想查看单个程序的耗时,一般使用time命令。
程序名之前加上time命令,会在程序执行完毕以后,默认显示三行统计。
real: 程序从开始运行到结束的全部时间,这是用户能感知到的时间,包括 CPU 切换去执行其他任务的时间。 user: 程序在 User space 执行的时间 sys: 程序在 Kernel space 执行的时间 user和sys之和,一般情况下,应该小于real。但如果是多核 CPU,这两个指标反映的是所有 CPU 的总耗时,所以它们之和可能大于real。
User space vs kernel space Using the Linux Top Command Understanding Linux CPU stats What do ‘real’, ‘user’ and ‘sys’ mean in the output of time(1)?
用户空间与内核空间
现在操作系统都是采用虚拟存储器,那么对32位操作系统而言,它的寻址空间 (虚拟存储空间) 为4G (2的32次方) 。操作系统的核心是内核,独立于普通的应用程序,可以访问受保护的内存空间,也有访问底层硬件设备的所有权限。为了保证用户进程不能直接操作内核 (kernel) ,保证内核的安全,操作系统将虚拟空间划分为两部分,一部分为内核空间,一部分为用户空间。针对linux操作系统而言,将最高的1G字节 (从虚拟地址0xC0000000到0xFFFFFFFF) ,供内核使用,称为内核空间,而将较低的3G字节 (从虚拟地址0x00000000到0xBFFFFFFF) ,供各个进程使用,称为用户空间。
内核空间, 内核态, 核心态, Kernel Mode, Kernel space
在内核态,代码拥有完全的,不受任何限制的访问底层硬件的能力。可以执行任意的CPU指令,访问任意的内存地址。内核态通常情况下都是为那些最底层的,由操作系统提供的,可信可靠的代码来运行的。内核态的代码崩溃将是灾难性的,它会影响到整个系统。
—– In Kernel mode, the executing code has complete and unrestricted access to the underlying hardware. It can execute any CPU instruction and reference any memory address. Kernel mode is generally reserved for the lowest-level, most trusted functions of the operating system. Crashes in kernel mode are catastrophic; they will halt the entire PC.
内核总是驻留在内存中,是操作系统的一部分。内核空间为内核保留,不允许应用程序读写该区域的内容或直接调用内核代码定义的函数。
linux 驱动程序一般工作在内核空间,但也可以工作在用户空间。下面我们将详细解析,什么是内核空间,什么是用户空间,以及如何判断他们。
Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟地址空间也为0~4G。Linux内核将这4G字节的空间分为两部分。将最高的1G字节 (从虚拟地址0xC0000000到0xFFFFFFFF) ,供内核使用,称为"内核空间”。而将较低的3G字节 (从虚拟地址 0x00000000到0xBFFFFFFF) ,供各个进程使用,称为"用户空间) 。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。
Linux使用两级保护机制: 0级供内核使用,3级供用户程序使用。每个进程有各自的私有用户空间 (0~3G) ,这个空间对系统中的其他进程是不可见的。最高的1GB字节虚拟内核空间则为所有进程以及内核所共享。
内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和数据。不管是内核空间还是用户空间,它们都处于虚拟空间中。
虽然内核空间占据了每个虚拟空间中的最高1GB字节,但映射到物理内存却总是从最低地址 (0x00000000) 开始。对内核空间来说,其地址映射是很简单的线性映射,0xC0000000就是物理地址与线性地址之间的位移量,在Linux代码中就叫做PAGE_OFFSET。
内核空间和用户空间之间如何进行通讯?
内核空间和用户空间一般通过系统调用进行通信。
如何判断一个驱动是用户模式驱动还是内核模式驱动? 判断的标准是什么?
用户空间模式的驱动一般通过系统调用来完成对硬件的访问,如通过系统调用将驱动的io空间映射到用户空间等。因此,主要的判断依据就是系统调用。
内核空间和用户空间上不同太多了,说不完,比如用户态的链表和内核链表不一样;用户态用printf,内核态用printk;用户态每个应用程序空间是虚拟的,相对独立的,内核态中却不是独立的,所以编程要非常小心。等等。
还有用户态和内核态程序通讯的方法很多,不单单是系统调用,实际上系统调用是个不好的选择,因为需要系统调用号,这个需要统一分配。
可以通过ioctl、sysfs、proc等来完成。
用户态 (User Mode)
在用户态,代码不具备直接访问硬件或者访问内存的能力,而必须借助操作系统提供的可靠的、底层的API来访问硬件或者内存。由于这种隔离带来的保护作用,用户态的代码崩溃 (Crash) ,系统是可以恢复的。我们大多数的代码都是运行在用户态的。
—– In User mode, the executing code has no ability to directly access hardware or reference memory. Code running in user mode must delegate to system APIs to access hardware or memory. Due to the protection afforded by this sort of isolation, crashes in user mode are always recoverable. Most of the code running on your computer will execute in user mode.
内核态和用户态
当一个任务 (进程) 执行系统调用而陷入内核代码中执行时,我们就称进程处于内核运行态 (或简称为内核态) 。此时处理器处于特权级最高的 (0级) 内核代码中执行。当进程处于内核态时,执行的内核代码会使用当前进程的内核栈。每个进程都有自己的内核栈。当进程在执行用户自己的代码时,则称其处于用户运行态 (用户态) 。即此时处理器在特权级最低的 (3级) 用户代码中运行。当正在执行用户程序而突然被中断程序中断时,此时用户程序也可以象征性地称为处于进程的内核态。因为中断处理程序将使用当前进程的内核栈。这与处于内核态的进程的状态有些类似。
为什么要区分Kernel Mode 和 User Mode呢?答案是隔离保护,使得系统更稳定。
http://blog.csdn.net/zhangskd/article/details/6956638
http://www.cnblogs.com/clover-toeic/p/3754433.html
http://www.ruanyifeng.com/blog/2016/12/user_space_vs_kernel_space.html
Author -
LastMod 2017-04-25