Linux 内存虚拟地址介绍
🐧 Linux内核空间与用户空间详解
✨ 核心概念对比
| 特性维度 | 用户空间(UserSpace) | 内核空间(KernelSpace) |
|---|---|---|
| 权限级别 | Ring 3 (低权限) | Ring 0 (最高权限) |
| 内存布局 (32位) | 0x00000000 - 0xBFFFFFFF (3GB) | 0xC0000000 - 0xFFFFFFFF (1GB) |
| 内存布局 (64位) | 0x0000000000000000 - 0x00007FFFFFFFFFFF (128TB) | 0xFFFF800000000000 - 0xFFFFFFFFFFFFFFFF (128TB) |
| 运行内容 | 普通应用程序 (如vim, gcc, bash) | 操作系统内核、设备驱动、系统资源管理 |
| 硬件访问 | 不能直接操作硬件,必须通过系统调用 | 直接操作硬件资源 |
| 稳定性影响 | 进程崩溃通常只影响自身 | 崩溃会导致整个系统崩溃 |
| 内存分配接口 | malloc() / mmap() / brk |
kmalloc() / vmalloc() / slab |
📖 1. 什么是内核空间和用户空间?
现代操作系统采用虚拟内存技术,为每个进程提供一个独立的、连续的虚拟地址空间。Linux将此空间划分为两部分:
-
用户空间 (User Space):这是普通应用程序运行的环境。它运行在CPU的低特权级别(如x86架构的Ring 3),无法直接访问硬件设备或其他进程的内存。每个进程都有自己独立的用户空间,彼此隔离。
-
内核空间 (Kernel Space):这是操作系统内核运行的环境。它运行在CPU的高特权级别(如x86架构的Ring 0),具有对硬件和系统资源的完全访问权。内核空间由所有进程共享,但只有内核代码本身可以驻留于此。
这种划分是操作系统存储器保护机制的核心一环,旨在保障系统的安全性、稳定性和效率。
🔍 2. 为什么需要这种划分?
内核空间和用户空间的分离主要基于以下几个目的:
-
安全性:将用户程序与内核隔离,防止用户程序的错误或恶意行为破坏内核,从而保证系统的稳定性和安全。
-
稳定性:即使某个用户空间的应用程序崩溃,也不会导致整个操作系统崩溃,只有当前进程会终止。
-
效率:内核空间可以直接访问硬件,执行效率更高。同时,这种划分使得系统功能模块化,便于开发和维护。
🗺️ 3. 内存地址布局
32位系统
在32位Linux系统中,4GB(2^32字节)的虚拟地址空间通常被划分为:
-
用户空间:较低的3GB(地址范围
0x00000000到0xBFFFFFFF),供各个进程使用。 -
内核空间:较高的1GB(地址范围
0xC0000000到0xFFFFFFFF),供内核使用,并由所有进程共享。
64位系统
在64位系统上,地址空间要大得多:
-
用户空间:通常为低128TB(例如,地址范围
0x0000000000000000到0x00007FFFFFFFFFFF)。 -
内核空间:通常为高128TB(例如,地址范围
0xFFFF800000000000到0xFFFFFFFFFFFFFFFF)。
每个进程都认为自己拥有完整的地址空间,但通过内存管理单元(MMU)和页表,操作系统将虚拟地址映射到物理地址,并确保用户进程无法访问内核空间的内存。
🐧 Linux虚拟地址
📖 1. 地址空间隔离
每个进程有自己独立的虚拟地址空间,它们在逻辑上是隔离的。这种隔离性是通过使用独立的页表来实现的。
每个进程都有自己的页表,用于将虚拟地址映射到不同的物理内存页上。
📖 2. 地址空间的映射关系
Linux使用分页机制将虚拟地址空间划分为固定大小的页,通常为4KB。每个进程的页表记录了虚拟地址和物理地址之间的映射关系。
这样,不同进程的相同虚拟地址可以映射到不同的物理内存页上。
📖 3. 地址空间布局的随机性
为了提高系统的安全性,现代操作系统(包括Linux)通常会引入地址空间布局的随机性技术,即地址空间随机化(ASLR)。
这种技术会在每次进程启动时,随机化虚拟地址空间的布局,使得相同的程序在不同的运行实例中分配到的虚拟内存地址是不同的。
📖 4. 进程间的地址转换
当进程访问虚拟地址时,操作系统内核负责将虚拟地址转换为对应的物理地址。
不同进程通过自己的页表来进行地址转换,确保它们在不同的虚拟地址空间中访问不同的物理内存。
🗺️ 5. 相同的虚拟内存地址
a.共享内存:进程可以使用共享内存机制将一块物理内存映射到多个进程的虚拟地址空间中。
在这种情况下,多个进程将访问相同的物理内存,因此它们会有相同的虚拟内存地址。
b.进程克隆:Linux提供了进程克隆(fork)机制,允许一个进程创建一个与自己相同的副本。
这种情况下,父进程和子进程会共享相同的虚拟内存地址空间,直到其中一个进程对内存进行修改时才会进行复制。
需要注意的是,上述特殊情况下的相同虚拟内存地址通常是有意而为之,并且是在特定的机制和操作下产生的。
在普通的进程执行中,不同进程会被分配不同的虚拟内存地址,以确保各个进程的隔离性和安全性。
参考文献
Linux内核空间与用户空间详解 - LeeHang - 博客园 (cnblogs.com)
浙公网安备 33010602011771号