Linux系统内存、文件系统分布与启动流程

zix 2024-7-8 142 7/8

1.32位系统内存分布

        在32位系统中,每一个进程具有独立的4GB虚拟运行空间,现代Linux系统由MMU进行虚拟内存向物理内存的映射。但也有少量的嵌入式系统其并无MMU,工程师在开发程序的时候需要特殊关注。

        各进程之间相不干扰,虚拟内存地址是按需映射的,程序刚开始运行的时候,可能只映射了.text段和少量的栈页。

        Linux系统内核本质也是一个程序,只不过其单独跑在0xC000_0000以上的内存空间下面是Linux系统的内存分布。

        大部分情况下,Linux系统的用户态和内核态按照3:1进行分割,

----------------0xFFFF_FFFF

内核空间

        每个程序都可以由自己的虚拟内存空间,但是对于0xC000_0000以上的内存空间,其虽然仍是虚拟内存,此时已经通过页表映射到了同一块物理内存,为系统内核空间。

----------------0xC000_0000(栈底bottom,封闭)

栈空间

----------------(栈顶top)

堆空间(动态分配,向上分配)

----------------

数据段

.bss未初始化或初始化为0的全局变量和静态局部变量

        这段数据在程序保存的时候不会占用磁盘空间,其在程序载入的时候自动初始化为0。

.data初始化的全局变量和静态局部变量

        初始化后非0的变量以及static变量,其特征是在程序运行过程中可能会发生修改,比如在程序中定义int a = 10,a将放入到.data段。

.rodata(只读常量区)

        主要存储的数据为字符串常量、const修饰的全局变量或者静态变量、常量数组、结构体、部分浮点数(编译器可能将大的浮点常量放入.rodata,小浮点常量直接放在.text段、switch跳转表。

const int a = 10;         //如果其是全局变量,则存储在.rodata段,如果是在函数内的局部变量则存储在栈上
static const int b = 10;  //同上,但是尽管声明在函数内部,其也仅初始化一次,故编译器通常将其编译进入.rodata段
char *p = {"hello world"}  //hello world放在.rodata段,p作为已初始化的变量放在.data段

        特别注意的是,如果const int a = 10声明在函数内部(局部静态变量),其可能存储在栈空间上,在每次函数调用的时候都会从栈上申请新的内存空间。

----------------

代码段,分为.text和.init两段(只读)

.text段(存储用户指令)

.init段(存储系统初始化程序)

----------------0x0804_8000

保留区(128M)

----------------0x0000_0000

        关于数据段,通俗而言,一个数据如若只读无法被修改,其通常存储在.rodata段,一个数据如果在运行过程中可能面临修改,则其一般初始化在.data段,一个变量如果未被初始化,则其通常存储在.bss段。存储在.rodata段的数据如果受到了指针的读取则可能会导致段错误。

2.Linux系统启动流程

        在硬件上电后,CPU从一个固定的地址读取程序,这个地址通常是boot/BIOS ROM芯片映射地址,具体取决于系统类型, 在X86平台上通常为BIOS芯片,部分为UEFI,同时,在部分嵌入式系统上可能没有独立的这个芯片,但是其集成在了Soc内,在出场的时候就已经固化了不允许修改升级。这部分程序通常用于POST自检、硬件初始化、提供简单硬件接口(底层服务)以及寻找bootloader。

        完成这部分固定程序执行后,运行启动引导程序(bootloader),在Linux中被称为uboot程序,在Windows中被称为BIOS程序,随后加载linux系统内核,交由内核执行加载rootfs根文件系统,随后加载驱动程序执行脚本文件,随后提供脚本终端,执行应用程序。

        根文件系统会提供一个根目录,提供shell终端,后续有其他U盘或者拓展盘都是在根文件系统下的。根文件系统下的各个文件夹存储的文件如下

目录 含义 存放内容
bin binary 存储基本用户指令,例如ls、cp、cat等,现代Linux系统通常将其放置在/usr/bin目录下并使用符号链接到根目录下
sbin system binary  存储系统管理指令,通常需要sudo权限,例如ip、reboot等,现代Linux系统通常将其放在/usr/sbin目录下
boot boot 启动相关文件,包括内核(vmlinuz)、内核启动临时根文件系统(initramfs)、GRUB (引导加载程序,在嵌入式设备中为uboot)配置等。
dev devices 设备文件,硬件的抽象接口,在Linux中,一切皆文件,即使是硬件也被抽象为各个文件
etc Etcetera/Editable text config 系统配置文件,存储如ssh、nginx、apt等程序的系统配置文件
home home 用户主目录,存储各个用户的文件夹,如/home/admin等
media media 媒体挂载目录,例如插入的U盘将会默认显示在该位置
mnt mount 临时挂载点,可以临时挂载各类磁盘,也可以在虚拟机中挂载共享文件夹
opt optional 可选第三方软件包,例如各种商业软件以及第三方软件
proc process 虚拟文件系统,存储内核和进程的实时信息,是内存中的文件的映射(不是磁盘存储数据)
root root root用户主目录
srv service 存储各种服务提供的数据,比如web服务器站点文件以及FTP文件
sys system 虚拟文件系统,暴露内核、设备、驱动等信息,与proc一样是内存中存储文件的映射。
tmp temp 临时文件,所有用户可写,重启后通常自动清理
usr unix system resource 用户级程序和只读文件,包含/usr/bin和/usr/lib等常用命令
var variable 可变数据文件,包含各种经常变化的内容,例如日志(/var/log)、缓存(/var/cache)、数据库文件等

        在linux系统下,一共有七种文件,他们分别是:

        - 规则文件    d 目录文件    p 管道文件    s 套接字文件    l 链接文件    c 字符设备文件    b 块设备文件    

        特别注意,目录不是文件夹,目录不是文件夹,目录不是容器,其只是一个文件,只记录了文件夹(容器)的信息。

        90%以上的零件只能以字节为最小单位访问,而块设备以块为单位访问,且块设备可以随机访问,字符设备不可以,字符设备通常是无缓冲的,块设备使用缓冲区来存放临时数据,待数据成熟后一次性刷新到设备。

        字符设备只能一个字符一个字符进行读取写入,常见的字节设备有鼠标、键盘等,90%以上的设备都是字符设备,块设备以固定大小数据块为单位进行读写,常见的块设备有磁盘、U盘、光盘等,块设备通常有内核缓冲区提升性能,字符设备可直接与用户空间交换数据。‌‌‌

 

- THE END -

zix

9月12日22:23

1

非特殊说明,本博所有文章均为博主原创。

粤公网安备44011302005765号