一、内核内存布局
64
位
Linux
一般使用
48
位来表示虚拟地址空间,
42位表示物理地址,通过命令:
cat /proc/cpuinfo
。
ARM64
架构处理器采用
48
位物理寻址机制,最大可寻找
256TB的物理地址空间。对于 目前应用完全足够,不需要扩展到
64
位的物理寻址。虚拟地址也同样最大支持
48位寻址,所以在处理器架构设计上,把虚拟地址空间划分为两个空间,每个空间最大支持
256TB
,
linux内核 在大多数体系结构上都把两个地址划分为:用户空间和内核空间。
用户空间:
0x0000_0000_0000_0000
至
0x0000_ffff_ffff_ffff
。
内核空间:
0xffff_0000_0000_0000
至
0xffff_ffff_ffff_ffff
。
二、堆管理
堆是进程中主要用于动态分配变量和数据 的内存区域,堆的管理对应程序员不是直接可见 的。因为它依赖标准库提供的各个辅助函数(其 中最重要的是
malloc)来分配任意长度的内存区。 malloc
和内核之间的经典接口是
brk系统调用,负责扩展
/
收缩堆。
堆是一个连续的内存区域,在扩展时自下至上增长。其中
mm_struct
结构,包含堆在虚拟地址空间中的起始和当前结束地址
(start_brk
和
brk)
。
brk系统调用用于指定堆在虚拟地址空间中新的结束地址(如果堆将要收缩,当然可以小于当前值)。
brk
系统调用通过
do_brk
增长动态分配区
(
内核源码分析
mm/mmap.c
)
:
三、补充内容
1、大内核锁BKL
Big Kernel Lock
(
BKL
)大内核锁,其为
Linux内核中的一种锁,与普通的锁原理基本一致,一旦进程获得
BKL,则进入被它保护的临界区,不但该临界区被上锁,所有被保护的临界区都会一起被锁住。
BKL有自动释放特性:在CPU_N上,如果当进程A持有BKL,则当CPU_N上面发生调度的时候,A进程持有的BKL被自动释放。
内核锁本质上也是自旋锁,但是它不同于自旋锁,不同在于自旋锁是不可以递归获取锁(会导致死锁),而大内核锁则可以递归获取锁,大内核锁作用是保护整个内核,而对应自旋锁则保护共享资源。使用大内核锁的时候保持锁的时间太长,导致严重影响系统性能和可伸缩性。
#define lock_kenel() do{}while(0)
#define unlock_kernel() do{}while(0)
原子操作对整数操作,自旋锁和信号量应用比较广泛。当临界区小应该选择自旋锁,反之应该选择信号量。
大内核锁一般使用在驱动、文件系统等。
大内核锁从
Linux 2.6.39已被淘汰原因在此不再深入讨论。
2、per-CPU计数器
内核借助如下数据结构实现per-CPU
Linux
操作系统,特别是针对
SMP
或者
NUMA架构的多
CPU
系统的时候,描述每个
CPU
的私有数据的时候,Linux操作系统提供了
per_cpu
机制。
【定义】
per_cpu
机制就是让每个
CPU都有自己的私有数据段,便于保护与访问。
引入所谓per_cpu计数器,来加速SMP系统上计数器操作。基本原理:计数器的准确值存储在内存中某一个地址,准确值所在内存位置之后是一个数组,每个数组对应于系统中一个CPU。
Linux系统特殊是针对SMP或者NUMA架构的多CPU系统的时候,主要描述每个CPU私有数据的时候,系统提供该机制per-cpu。
三种CPU模式:x86 x64 ia64
x86表示基于x86指令集安装模式;x64表示64位系统程序;ia64一般电脑不涉及这个东西,用于企业级服务器的。
ia64处理器,英特尔安藤架构,基于a64处理器架构的服务器具有64位运算能力,64寻址空间,64位数据通路。