思考:每个进程都需要独立的资源分配,内核也是程序(进程的概念),因此也要独立分配资源。而且为了系统的安全和可靠,访问底层的硬件资源,只能由操作系统来发起,用户程序不允许直接访问硬件资源。
1、从功能角度看用户空间和内核空间
内核空间主要是指操作系统运行时所使用的用于程序调度、虚拟内存的使用或者连接硬件资源等的程序逻辑。
为何需要内存空间和用户空间的划分呢?很显然和前面所说的每个进程都独立使用属于自己的内存一样,为了保证操作系统的稳定性,运行在操作系统中的用户程序不能访问操作系统所使用的内存空间。这也是从安全性上考虑的,如访问硬件资源只能由操作系统来发起,用户程序不允许直接访问硬件资源。
如果用户程序需要访问硬件资源,如网络连接等,可以调用操作系统提供的接口来实现,这个调用接口的过程也就是系统调用。每一次系统调用都会存在两个内存空间的切换,通常的网络传输也是一次系统调用,通过网络传输的数据先是从内核空间接收到远程主机的数据,然后再从内核空间复制到用户空间,供用户程序使用。这种从内核空间到用户空间的数据复制很费时,虽然保住了程序运行的安全性和稳定性,但是也牺牲了一部分效率。
2、从内存角度看用户空间和内核空间
Linux简化了分段机制,使得虚拟地址与线性地址总是一致,因此,Linux的虚拟地址空间也为0~4G Linux内核将这4G字节的空间分为两部分。将最高的1G字节(从虚拟地址0xC0000000到0xFFFFFFFF),供内核使用,称为"内核空间"。而将较低的3G字节(从虚拟地址 0x00000000到0xBFFFFFFF),供各个进程使用,称为“用户空间”)。因为每个进程可以通过系统调用进入内核,因此,Linux内核由系统内的所有进程共享。于是,从具体进程的角度来看,每个进程可以拥有4G字节的虚拟空间。
3、内核空间和用户空间的交互
通过系统调用实现内核和用户空间的交互。现在,越来越多的应用程序需要编写内核级和用户级的程序来一起完成具体的任务,通常采用以下模式:首先,编写内核服务程序利用内核空间提供的权限和服务来接收、处理和缓存数据;然后编写用户程序来和先前完成的内核服务程序交互,具体来说,可以利用用户程序来配置内核服务程序的参数,提取内核服务程序提供的数据,当然,也可以向内核服务程序输入待处理数据。