64/32位Linux系统的差异(地址空间布局,系统调用)对比分析

编程入门 行业动态 更新时间:2024-10-24 12:24:09

64/32位Linux<a href=https://www.elefans.com/category/jswz/34/1770742.html style=系统的差异(地址空间布局,系统调用)对比分析"/>

64/32位Linux系统的差异(地址空间布局,系统调用)对比分析

Ubuntu从17.10开始不再官方支持32位(i386)架构(严格的说是从18.04开始的,因为17.10不支持32位的PC版,但是支持32位的SERVER版,但是偶数稳定版确实是从18.04开始的),只支持64位(amd64)架构,这是因为随着时间的推移,64位系统变得越来越普遍,并且可以更好的利用现代计算机的硬件性能和内存容量,此外,随着软件的发展和更新,许多应用程序都不再提供32位版本,而只提供64位版本,这也促使ubuntu停止更新32位架构。尽管如此,ubuntu18.04仍然提供了32位版本的软件包和库,以便支持老旧系统和应用程序。镜像下载链接:

Index of /releases

内核的架构是由内核自身决定的,和发行版无关,之所以提到UBUNTU是因为后面的实验是在UBUNTU环境下进行的。Linux内核在 32位和64位架构上有着不同的地址空间范围,在32位架构中,地址空间一共32位,从[0x00000000,0xFFFFFFFF],总共是4GB,这个地址空间被分成用户空间和内核空间两个部分,不同的架构划分方式有所不同,通常是按照3G用户1G内核的分法。

相比之下,在64位架构中,范围为[0x0000000000000000,0xFFFFFFFFFFFFFFFF],这个范围如此之大,以至于当前没有任何应用需要这么大的空间,所以实际上这个地址空间并不会被占满,而是用户空间和内核空间分别占用一部分,剩下的保留不用。当前的主流实现是,64位地址空间,Linux64位操作系统仅使用低47位,高17位作为扩展(全0或者全1),所以实际用到的地址空间为[0x0000000000000000,0x00007FFFFFFFFFFF](用户态)和[0xFFFF800000000000, 0xFFFFFFFFFFFFFFFF](内核态)。其余地址空间都是保留不用的。如下图所示:

地址映射范围: 

实际运行用户态用例查看

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{while(1){printf("%s line %d, helloworld.\n", __func__, __LINE__);sleep(1);}return 0;
}

测试发现用户态地址空间确实和上面的分析吻合。

内核地址空间呢?内核地址空间无法通过pmap或者/proc/节点查看,不用急,我们还有/proc/kallsyms节点,它保留了内核中的符号信息,接取一小段分析一下,发现却是落到了上图中得内核地址空间范围内,但是似乎只局限在某个狭窄的区域,并没有从0xFFFF800000000000开始。

实际上,查看内核文档Documentation/x86/x86_64/mm.rst得知,内核代码段仅仅占用了内核空间的一小部分,剩下的部分也都各有所属,被内核的其它机制瓜分了,为了将来拓展内核功能,有些地址空间被设置为保留。

在4.14内核上的描述更简洁清晰一些:

图中可以看到,0xffffffff80000000开始的地址空间确实属于内核代码和数据的地盘,和上面分析/proc/kallsyms结论是吻合的。

PAGE_OFFSET

物理地址与线性地址之间的位移量,在Linux代码中就叫做PAGE_OFFSET, 在32位的内核中,这个值一般是0xc0000000.PAGE_OFFSET 代表的是内核空间和用户空间对虚拟地址空间的划分,不同的体系结构定义和值都不同。比如在32位系统中3G-4G属于内核使用的内存空间,所以 PAGE_OFFSET = 0xC0000000。在X86-64架构下是ffff880000000000。内核程序可以可以访问从PAGE_OFFSET 之后的内存。

可以看到,在开启CONFIG_DYNAMIC_MEMORY_LAYOUT(通过CONFIG_RANDOMIZE_MEMORY控制)的情况下,PAGE_OFFSET的值是动态变化的,取自于page_offset_base变量。

我们可以将一个PAGE的物理地址和内核线性地址的偏移打印出来,如果不出意外,应该和PAGE_OFFSET相等。下图可以看到,计算得到的OFFSET和PAGE_OFFSET他们确实是一致的。

page offset 是线性地址和物理地支之间的转换因子

CONFIG_DYNAMIC_MEMORY_LAYOUT打开情况下:

如果不设置CONFIG_DYNAMIC_MEMORY_LAYOUT,则PAGE_OFFSET为内核设置的固定值:

DUMP系统的PAGE TABLE,起始于0xffff888000000000.

从内核镜像中分析内核符号

分析vmlinux和vmlinux.lds文件都可以得到关键的符号地址信息:

可以看到_stext起始地址为0xffffffff81000000,吻合图中的分布.

vmlinux.lds的定义导出关键符号表信息,比如_end.

也就是说,内核代码+数据+bss=0xffffffff8402c000-0xffffffff81000000=0x302c000.

32位系统安装

32位系统已经很少见了,便于分析,用QEMU-KVM安装一台ubuntu-16.04.3-desktop-i386.iso虚拟机。参考博客:

ubuntu18.04下pass-through直通realteck PCI设备到qemu-kvm虚拟机实践_papaofdoudou的博客-CSDN博客

qemu-img create -f qcow2 i386.img 20G
sudo virt-install --virt-type kvm --name i386 --ram 4096 --vcpus 4 --machine q35 --cdrom ~/Workspace/iso/ubuntu-16.04.3-desktop-i386.iso --disk i386.img --network network=default --graphics vnc,listen=0.0.0.0 --noautoconsole
sudo virsh vncdisplay i386
:1
gvncviewer 127.0.0.1:1

更多推荐

64/32位Linux系统的差异(地址空间布局,系统调用)对比分析

本文发布于:2024-03-06 17:36:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1715950.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:系统   差异   地址   空间布局   Linux

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!