linux用户空间与内核空间(内核空间和用户空间的区别)
linux内存管理之用户空间与内核空间详解
Linux操作系统运行在内核空间,应用程序运行在用户空间,两者之间不能简单地使用指针传递数据,因为Linux采用虚拟内存机制,用户空间的数据可能被换出。内核空间使用用户空间指针时,对应的数据可能不在内存中。
Linux内核使用段页式地址映射模型,进程代码中的地址为逻辑地址,通过段页式映射后,才能真正访问物理内存。
Linux内核地址空间通常分为用户空间和内核空间,其中用户空间范围为0~3G,内核空间范围为3~4G。注意,这里指的是32位Linux内核的地址空间划分,64位内核的地址空间划分有所不同。
内核空间的高端内存概念源于物理内存的限制。当内核模块代码或线程访问内存时,逻辑地址需要一对一映射到物理内存地址。例如,逻辑地址0xc0000003对应物理地址0×3,以此类推。如果内核逻辑地址空间为0xc0000000~0xffffffff,那么物理内存范围只能访问0×0~0×40000000,即最多访问1G物理内存。若安装8G物理内存,内核只能访问前1G内存,后面的7G内存无法访问。
为了解决这个问题,x86架构将内核地址空间划分为三部分:ZONE_DMA、ZONE_NORMAL和ZONE_HIGHMEM。ZONE_HIGHMEM即为高端内存区域,它是内存高端内存概念的来源。
在x86结构中,内核地址空间分为如下三部分:
ZONE_DMA:内存开始的16MB
ZONE_NORMAL:从16MB到896MB
ZONE_HIGHMEM:从896MB至结束
Linux内核高端内存的理解在于,通过将高端内存划分为特定区域,如ZONE_HIGHMEM,允许内核使用有限的地址空间访问所有物理内存。当内核想访问超过896MB的物理内存时,它可以在高端内存区域找到相应的空闲逻辑地址空间,借用一段时间来映射到物理内存,完成访问后释放这段逻辑地址空间,以便其他进程或代码使用。
例如,内核想要访问从物理地址0×80000000开始的1MB内存,可以找到一段1MB大小的空闲逻辑地址空间,借用一段时间进行映射,完成访问后释放这段逻辑地址空间。
高端内存的基本思想是借用一段地址空间建立临时映射,用完后释放,实现循环使用,从而访问所有物理内存。
在Linux内核管理中,高端内存的使用涉及到复杂的地址映射和释放机制。为了支持高端内存,内核将内存划分为VMALLOC_START~VMALLOC_END、KMAP_BASE~FIXADDR_START和FIXADDR_START~4G等部分。对于高端内存的映射,有三种方式:映射到“内核动态映射空间”、持久内核映射和临时映射。
通过使用这些映射方式,Linux内核能够高效地管理高端内存,实现访问所有物理内存的功能。当进程或内核模块占用逻辑地址空间不释放时,系统会提醒释放,以避免内存资源的浪费。
综上所述,Linux内存管理中的用户空间与内核空间通过虚拟内存机制和地址映射模型实现隔离,内核使用特定的地址空间和映射技术访问所有物理内存,而用户进程则受限于用户空间。这种设计保证了系统的稳定性和安全性,同时也支持了多进程和多任务的高效运行。
Linux用户空间与内核空间(理解高端内存)
理解Linux用户空间与内核空间的高端内存机制,首先需要知道操作系统和驱动程序运行在内核空间,而应用程序运行在用户空间,两者之间的数据传输受限于虚拟内存映射,用户空间数据可能被换出,导致内核使用用户空间指针时,对应的数据可能不在内存中。
Linux内核采用了x86的段页式地址映射模型,将进程的逻辑地址映射到物理内存。通常,32位内核地址空间划分为0~3G为用户空间,3~4G为内核空间。但这种简单的映射方式限制了内核对物理内存的访问范围,只能访问1GB,即使机器有更多内存。
为了解决这个问题,内核引入了高端内存(ZONE_HIGHMEM),通过动态分配逻辑地址空间,临时建立映射来访问超过预设范围的物理内存。例如,内核可能借入0xF8000000到0xFFFFFFFF的逻辑地址空间,对应物理内存的1024MB至8GB,实现对所有物理内存的访问,用完后归还。
需要注意的是,如果内核进程长时间占用高端内存不释放,会导致地址空间紧张,影响其他进程的内存映射。这个管理方式类似于写字楼的洗手间管理,需要用户合理使用并及时归还资源。
Linux内核将高端内存划分为不同的区域,包括VMALLOC_START~VMALLOC_END、KMAP_BASE~FIXADDR_START和FIXADDR_START~4G,通过不同的函数如alloc_page()来分配和映射这些内存。高端内存映射有三种方式,分别是内核动态映射、永久内核映射和临时映射,每种映射方式都有其特定的用途和释放机制。
最后,用户空间和内核空间的内存访问权限不同,用户进程只能访问3GB(32位系统)或超过512GB(64位系统)的物理内存,而内核可以访问所有物理内存。虚拟内存映射和物理地址之间的关系复杂,但Linux通过精心设计的机制保证了内核和用户空间的隔离和高效共享。
Linux的内核空间和用户空间是如何划分的(以32位系统为例)
通常32位Linux内核地址空间划分0~3G为用户空间,3~4G为内核空间。地址分配如下图所示
内核地址空间分布
直接映射区:线性空间中从3G开始最大896M的区间,为直接内存映射区,该区域的线性地址和物理地址存在线性转换关系:线性地址=3G+物理地址。
动态内存映射区:该区域由内核函数vmalloc来分配,特点是:线性空间连续,但是对应的物理空间不一定连续。vmalloc分配的线性地址所对应的物理页可能处于低端内存,也可能处于高端内存。
永久内存映射区:该区域可访问高端内存。访问方法是使用alloc_page(_GFP_HIGHMEM)分配高端内存页或者使用kmap函数将分配到的高端内存映射到该区域。
固定映射区:该区域和4G的顶端只有4k的隔离带,其每个地址项都服务于特定的用途,如ACPI_BASE等。