资讯专栏INFORMATION COLUMN

程序员的自我修养—精华(elf文件、虚拟内存)

qpwoeiru96 / 3406人阅读

摘要:即注意,局部变量属于的是指令而对于全局变量局部,这些都是数据即这些,在程序的运行,自始至终都是占着内存的其中,已经初始化的且不为的变量是在段,即段的大小是。

catalog

程序

我们写的程序,需要经过(编译,链接)得到 最终的exe/elf(产生到 磁盘上)。

如果我们要运行他,必须要把他加载到 内存里! 因为cpu访问内存的速度 要比访问磁盘,速度快千万倍

cpu的位数,是指: 他一次性能够进行运算的 整数的宽度,因为cpu是在ALU里运算数据
所以, cpu的位数 其实是 ALU的宽度(即,数据总线的 条数)
但是, cpu的位数 不一定等于 地址总线的 条数,他等于的是 数据总线的条数


比如虚拟地址是4GB,(物理内存不一定是4GB!!),他的布局格式是:

  • [0 - 3GB]这个地址区域,称为 用户空间

    • [0 - 128MB] 是forbidden禁止的! 他是禁止访问的,连访问都不能,更不能写!!

    • [128MB - 3GB],这是我们程序可以使用的 虚拟地址区域
      第一个区域,他划分为有: [.text] [.data] [.bss]
      我们知道,一个程序无非是:(指令) + (数据)
      指令是在:.text段, 数据是在:.data段 和 .bss段

      紧接着 第二个区域: heap 堆空间

      第三个区域:用来放到dll共享库的!
      比如,你用了很多scanf这种函数,他在头文件里 只有声明,并没有定义。 但是,等到链接时,程序会自动的 链接一些系统的库。

      第四个区域: [.stack]
      因为,我们程序的运行 就是从入口函数开始递归,这个段就是供我们函数运行的;比如,你的局部变量 就会在这个.stack段里。

      第五个区域: 放命令行参数、环境变量。main函数的参数 argv这些

  • [3 - 4GB]这个地址区域,称为 内核空间,即OS运行的空间
    第一个区域是: ZONE_DMA DMA: direct memory access,加速 磁盘和内存 交换数据用的
    在没有DMA技术前,磁盘和内存交换数据时: 磁盘数据 必须经过总线,流经 cpu的寄存器,最终才能到达内存
    这是对cpu的 极大浪费。
    有了DMA,比如加载一个文件 从磁盘 通过总线 到内存中时,不需要使用cpu的寄存器!!!
    cpu遇到这种情况,他就会空闲下来,来调度其他的进程!!

      第二区域: `ZONE_NORMAL`  第三区域: `ZONE_HIGHMEM`

int a = 1;int b = 0;int c;static int d = 1;static int e = 0;static int f;int main(){	int g = 1;	int h = 0;	int i;		static int j = 1;	static int k = 0;	static int l;	return 0;}

这个程序中,属于 指令的是: int main(){ int g = 1; int h = 0; int i; return 0; },即他们是在 .text段。
因为这些,要么是函数,要么是局部变量,可以多次调用 是属于指令。 即注意,局部变量 属于的是 指令!

而对于: 全局变量 + 局部static,这些都是 数据(即这些,在程序的运行,自始至终 都是占着内存的)
其中,已经初始化的 且不为0 的变量 a,d,j 是在 .data段,即.data段的大小 是12。

常量(比如"hello"),他是在 .rodata段

没有初始的 或 初始为0的,是在.bss段。
关于.bss段,有几个信息:

  • 在.obj文件里, [elf header] [.text] [.data] [.bss] [.comment] [section table]
    但其实你会发现,.comment段 和 .bss段 在文件里的地址,其实是一样的!!
    而这两个段 大小都不是0,为什么是一样的呢?
    其实,.bss段 他在obj文件里 其实是不占空间的!!! 其实就没有这个段,.data后面就是.comment
    .bss段 只会占的是: 虚拟空间里的内存!! 而不占.obj文件里的空间

    而,这个.bss段 在.obj文件 是不存在的,那他怎么知道 这个段里的那些全局/static变量呢?
    通过读section table段表,他里面会记录 每个段的详细信息,bss的信息 可以通过他来获取

    .bss段,没必要在文件中存储。这是因为: .data段里存的 都是初始值,即程序一运行 这些值就必须初始化为(用户指定的值)
    但是,.bss段里的 他的值 都是0,就不用在文件里存储他了,这样减少文件的大小

  • 按理说,该有6个变量 是在.bss段。 但是,为什么1不是在.bss段呢?

    main.c	short x = 10; short y = 10;	extern void func();	int main(){		func();	}test.c	int x;	void func(){ x = 20; }

    这个项目,在c++里 肯定是错误的。因为有2个x,c++里 所有的符号变量/函数,都不能重名。
    而在c里,他存在 强符号(初始化了的) 和 弱符号(未初始化的)的区别,这里:short x是强符号,int x是弱符号
    (强符号:只能有1个,即初始化的 只能有1个)(弱符号:可以有多个,即未初始的 可以有多个,不管是什么类型)
    (在链接后,优先使用强符号; 没有强符号,则优先使用内存最大的弱符号)

    即,在项目进行链接完后,func()函数里 所使用的x,其实是:short x这个
    func函数里 他的汇编是: 往x 写4个字节的内存,这是在多带带编译test.c 就确定下来的汇编指令。
    而最终链接后,这个汇编指令 肯定是不变的,但这个x 并不是int,而是short
    所以,20的4字节是: 14 00 00 00,前面的14 00 给short x,后面的00 00 给short y,所以,最终:x = 20, y = 0 {x是指的short这个}

    int c;这个全局变量,他是不在.bss段的。
    因为: int b = 0;初始了,他是强符号 虽然c++没有强弱符号,但这个程序 也可能是c的!!
    int c;未初始,弱符号。 他会在另外一个COM段,不是在bss段。因为他可能被其他obj里的强符号所顶替
    其他的,都是static。static,是本文件可见!!!他是强制性的!!即,即使是一个static的弱符号,在本文件里 也不会被其他强符号替代!
    static还有个名字,是local,即本地的 本文件的。其他文件,也看不到这个文件里的static变量。


os会 运行很多的进程,这些进程 所使用的虚拟空间,其中他们的内核区域[3 - 4GB]区域 都是共享的,因为只有1个操作系统
但用户空间,他是 独立的,每个进程的 用户空间,肯定都是不同的。


当程序要运行时,即变成进程,要进行下面几个步骤:

  • 虚拟地址物理内存映射,创建 页目录 和 页表
  • 加载 .text段 和 .data段
  • 把该exe的入口地址,写到 pc寄存器里。
    ELF header里,有个entry point address。到时候这个进程运行时,这个地址 就会放到cpu的 pc寄存器里,即为该程序的入口地址

== 2:00 https://www.bilibili.com/video/BV1xf4y127AJ ==

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/121119.html

相关文章

  • 重学计算机组成原理(七)- 程序无法同时在Linux和Windows下运行?

    摘要:链接器会扫描所有输入的目标文件,然后把所有符号表里的信息收集起来,构成一个全局的符号表。这是一本难得的讲解程序的链接装载和运行的好书。 showImg(https://image-static.segmentfault.com/396/693/396693929-5d558865c3a7e_articlex); 既然程序最终都被变成了一条条机器码去执行,那为什么同一个程序,在同一台计算...

    ShowerSun 评论0 收藏0
  • 重学计算机组成原理(八)- 程序装载

    摘要:这个办法,在现在计算机的内存管理里面,就叫作内存分页和分段这样分配一整段连续的空间给到程序相比分页则是把整个物理内存空间切成一段段固定尺寸的大小而对应的程序所需要占用的虚拟内存空间,也会同样切成一段段固定尺寸的大小。 showImg(https://image-static.segmentfault.com/290/765/2907653835-5d580caf245fd_articl...

    Developer 评论0 收藏0
  • APP漏洞扫描用地址空间随机化

    摘要:同时,阿里聚漏洞扫描器有一个检测项叫未使用地址空间随机化技术该检测项会分析中包含的文件判断它们是否使用了该项技术。在版本上线前使用阿里聚安全漏洞扫描系统进行安全扫描,将安全隐患阻挡在发布之前。 前言 我们在前文《APP漏洞扫描器之本地拒绝服务检测详解》了解到阿里聚安全漏洞扫描器有一项静态分析加动态模糊测试的方法来检测的功能,并详细的介绍了它在针对本地拒绝服务的检测方法。 同时,阿里聚漏...

    LinkedME2016 评论0 收藏0
  • 震惊!这个操作系统应用加载只需要“毫秒级”耗时

    摘要:本文主要介绍应用程序加载如何做到毫秒级耗时。图不同视角看左边是从汇编器和链接器的视角来看这个文件,开头的描述了体系结构和操作系统等基本信息,并指出和在文件中的什么位置,在汇编和链接过程中没有用到,所以是可有可的,中保存了所有的描述信息。 1、背景 AliOS Thing 是AliOS家族旗...

    incredible 评论0 收藏0
  • 论快捷关机自我修养(正经序员多半是直接关机而不是这么花里胡哨)

    摘要:二对的修改一键关机写上后保存是调出这个程序,是关闭的意思,是时间秒的意思。这里为零是指立即关机。四主题到来快捷关机将文件右击选择发送到的桌面快捷方式这样就可以在桌面有个自己的快捷方式了。 ...

    Binguner 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<