重定位

操作系统-第4章习题解析

我只是一个虾纸丫 提交于 2019-12-04 12:21:06
第4章习题解析 1.为什么要配置层次式存储器? 答:这是因为:   a.设置多个存储器可以使存储器两端的硬件能并行工作。   b.采用多级存储系统,特别是Cache技术,这是一种减轻存储器带宽对系统性能影响的最佳结构方案。   c.在微处理机内部设置各种缓冲存储器,以减轻对存储器存取的压力。增加CPU中寄存器的数量,也可大大缓解对存储器的压力。 2.可采用哪几种方式将程序装入内存?它们分别适用于何种场合? 答:将程序装入内存可采用的方式有:绝对装入方式、重定位装入方式、动态运行时装入方式;绝对装入方式适用于单道程序环境中,重定位装入方式和动态运行时装入方式适用于多道程序环境中。 3.何为静态链接?静态链接时需要解决两个什么问题? 答:静态链接是指在程序运行之前,先将各自目标模块及它们所需的库函数,链接成一个完整的装入模块,以后不再拆开的链接方式。   将几个目标链接装配成一个装入模块时,需解决以下两个问题:     将相对地址进行修改。即将除第一个模块外的相对地址修改成装入模块中的相应的相对地址。     变换外部调用符号。即将每个模块中所用的外部调用符号,都变换为相对地址。 4.何谓装入时动态链接?装入时动态链接方式有何优点? 答:装入时动态链接是指将用户源程序编译后所得到的一组目标模块,在装入内存时,采用边装入边链接的一种 链接方式,即在装入一个目标模块时

重定位

守給你的承諾、 提交于 2019-12-03 13:40:37
一、链接地址   程序编译时指定的地址,通过-Ttext参数指定的地址,它是理论上程序在运行时所处的地址。 二、加载地址   程序在运行时实际所处理的地址。    注意:链接地址与加载地址不能保障一定一样。 三、位置有关代码   如果程序的链接地址与加载地址不符,程序就无法运行,或运行错误中的代码叫位置有关代码。 四、位置无关代码   如果程序的链接地址与加载地址不符,程序依然能够i有正确运行,这种代码叫位置无关代码。   可以简单的认为使用了BL的代码叫位置有关代码,而没有使用BL的叫位置无关代码。 五、再论S5PV210的启动过程   1.iROM中的固定程序会从SD中拷贝16~96KB的程序先进行环境初始化(设置时钟、初始化内存、开看门狗)。   2.然后再把剩余的程序从SD卡中拷贝到SDRAM中。   3.把开发板上的所有资源都初始化好,为OS的运行做好准备。   4.拷贝OS到SRAM中,启动OS。 六、什么是重定位   uboot为了兼容大多数CPU并不会这样,而先把uboot的前96KB拷贝到SRAM中,然后初始化,再把完整的uboot拷贝到SDRAM中。   因此uboot的前96KB的程序就会在不同的位置运行两次,所以一定会出现链接地址与加载地址不符的情况。   具体的做法是先把uboot拷贝到SRAM中只运行少量的位置无关代码,然后再把程序拷贝到正确位置

速读《深入理解计算机系统》

时光毁灭记忆、已成空白 提交于 2019-12-02 13:04:31
本周速读了《深入理解计算机系统》这本书,这本书从程序员的角度介绍了计算机系统的内在运作,展示了一些本质概念是如何实际的影响应用程序的正确性、性能和实用性的。收获如下: 1、关于进程和线程 进程是操作系统对运行程序的一种抽象,是指计算机中已运行的程序,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。 线程有时被称为轻量级进程,是操作系统能够进行运算调度的最小单位。线程是进程中的一个实体,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源,同一进程中的多个线程之间可以并发执行。 2、几种数据传送指令 movl:传送双字,源操作数指定一个值,可以是立即数,可以存放在寄存器或存储器中。目的操作数指定一个位置,可以是寄存器或存储器地址。 movw:传送两个字节,当一个操作数为寄存器时,必须为下图中八个双字节寄存器元素中的一个。 movb:传递一个字节,当一个操作数为寄存器时,必须为下图中八个单字节寄存器元素中的一个。 movsbl和movzbl负责拷贝一个字节,并设置目的操作数中其余的位。 movsbl的源操作数是单字节的,并将高24位设置为源字节的最高位,然后拷贝到双字的目的中。 movzbl的源操作数是单字节的,在前面加24个0扩展到32位,然后拷贝到双字的目的中。 3、寄存器的使用惯例

内存管理

本小妞迷上赌 提交于 2019-12-01 13:20:26
内存 内存使用: 将程序放到内存中,PC指向开始地址,然后取指执行。 物理内存: 实际内存。 虚拟内存: 1. 每一个运行的进程,都会获得一个内存地址空间,这就是所谓的虚拟内存。 2. 这里面的所有地址都是虚拟的,和物理内存并不直接挂钩。 3. 这些虚拟地址所映射到的实际地址,可以是物理内存地址,也可以是页面文件的地址。 4. 如果物理内存小于这个虚拟地址的范围, 使用的时候可以将内存数据写入页面文件,通过清空内存数据,以提高物理内存的利用效率。 页面文件: 硬盘上的一块空间,在Windows下表现为一个文件。 这个页面文件存在的意义就是在物理内存被占用满以后, 将物理内存中的东西移动到硬盘上,腾出物理内存给需要的应用程序来使用。 内存管理 内存管理和虚拟内存管理: 内存管理包括: 程序装入等概念、 交换技术、 连续分配管理方式、 非连续分配管理方式(分页、分段、段页式)。 虚拟内存管理包括: 虚拟内存概念、 请求分页管理方式、 页面置换算法、页 面分配策略、 工作集、 抖动。 程序装入和链接 编译: 由编译程序将用户源代码编译成若干个目标模块。 链接: 由链接程序将编译后形成的一组目标模块,以及所需库函数链接在一起,形成一个完整的装入模块。 装入: 由装入程序将装入模块装入内存运行。 重定向(修改程序中的相对地址): 1. 编译时重定位的程序只能放在内存固定位置 2.

编译链接是如何得到可执行文件的呢?

让人想犯罪 __ 提交于 2019-12-01 04:29:46
盘古开天辟地!我们写了个C语言源文件,那从源文件到可执行程序这中间又发生了什么?编译,链接这些概念又是什么意思?带着对这些问题的好奇,我查了一些资料。其中,主要参考的是《程序员的自我修养》这本书和一些网上的博客。 在 windows 下经常只需要单击 Run 或者 Debug 就可以运行一个C语言程序,这种便利隐藏了背后的复杂机制,而我想知道这背后到底发生了什么。 本文所使用的系统是 ubuntu ,但这些概念也适用于 windows 下。 1. 编译源文件的四个阶段 假如我们写了一个很简单的 helloworld.c 程序: #include <stdio.h> int main(int argc, char *argv[]) { printf("Hello,World!\n"); return 0; } 我们都知道运行命令 gcc helloworld.c -o helloworld 便可以对这个文件进行编译,并命名可执行文件为 helloworld 。然后运行 ./helloworld Hello,World! 便可以执行该文件,但是这背后又经历了什么呢? 注意: 本文并不是一篇严谨的探讨编译过程的文章,只是我对这个问题了解过程的一个梳理。 1.1 预处理(preprocessing) 在预处理阶段,我们可以简单理解就是处理以"#"开始的那些预处理指令,比如说:

聊聊动态链接和dl_runtime_resolve

情到浓时终转凉″ 提交于 2019-11-30 12:21:42
写在前面 linux下的动态链接相关结构,重新回顾_dl_runtime_resolve的流程以及利用方法 动态链接相关结构 为了高效率的利用内存,多个进程可以共享代码段、程序模块化方便更新维护等,动态链接技术自然就出现了。不详细介绍位置无关代码和位置无关可执行程序这些基本知识,这里着重记录一下ELF实现运行时重定位为了提高效率做的各种工作和用到的结构。 动态链接的可执行文件装载过程和静态链接基本一样,OS读取可执行文件的头部信息,检查文件合法性后从Program Header中读取每一个Segment的虚拟地址、文件地址和属性,然后把他们映射到进程虚拟空间的相对位置。但是OS接下来不能把控制权交给可执行文件,因为动态链接中还有很多依赖于共享对象的无效地址,需要进一步处理。映射完成后,OS会启动一个动态链接器(Dynamic Linker)——linux下就是ld.so。这个动态链接器实际上也是一个共享对象,OS也会通过映射的方式把它载入进程的地址空间中。然后OS就会把控制权交给DL的入口地址,它会进行一系列初始化操作,根据当前环境参数对可执行文件进行动态链接工作。完成之后再把控制权转交给可执行文件。 pwn常见的so hell 动态链接器并非由系统配置或者环境参数决定,而是由ELF可执行文件自己决定!动态链接的ELF可执行文件中,有一个专门的段叫做.interp

我是如何学习写一个操作系统(八):内存管理和段页机制

最后都变了- 提交于 2019-11-29 00:48:30
前言 多进程和内存管理是紧密相连的两个模块,因为运行进程也就是从内存中取指执行,创建进程首先要将程序和数据装入内存。将用户原程序变成可在内存中执行的程序,而这就涉及到了内存管理。 内存的装入 绝对装入。 在编译时,如果知道程序将驻留在内存的某个位置,编译程序将产生绝对地址的目标代码。绝对装入程序按照装入模块的地址,将程序和数据装入内存。装入模块被装入内存后,由于程序中的逻辑地址与实际地址完全相同,故不需对程序和数据的地址进行修改。 可重定位装入。 在多道程序环境下,多个目标模块的起始地址通常都是从0开始,程序中的其他地址都是相对于起始地址的,此时应采用可重定位装入方式。根据内存的当前情况,将装入模块装入到内存的适当位置。装入时对目标程序中指令和数据的修改过程称为重定位,地址变换通常是装入时一次完成,所以成为静态重定位。 其特点是在一个作业装入内存时,必须分配器要求的全部内存空间,如果没有足够的内存,就不能装入,此外一旦作业进入内存后,在整个运行期间,不能在内存中移动,也不能再申请内存空间。 动态运行时装入 也成为动态重定位,程序在内存中如果发生移动,就需要采用动态的装入方式。 动态运行时的装入程序在把装入模块装入内存后,并不立即把装入模块中的相对地址转换为绝对地址,而是把这种地址转换推迟到程序真正要执行时才进行。因此,装入内存后的所有地址均为相对地址

操作系统

孤街醉人 提交于 2019-11-28 21:35:18
C的内存分配 32bitCPU可寻址4G线性空间, 每个进程都有各自独立的4G逻辑地址, 其中0~3G是用户态空间, 3~4G是内核空间, 不同进程相同的逻辑地址会映射到不同的物理地址中. 其逻辑地址其划分如下: 正文段(code segment/text segment, .text段): 或称代码段, 通常是用来存放程序执行代码的一块内存区域. 这部分区域的大小在程序运行前就已经确定, 并且内存区域通常属于只读, 某些架构也允许代码段为可写, 即允许修改程序. 在代码段中, 也有可能包含一些只读的常数变量, 例如字符串常量等 . CPU执行的机器指令部分. ( 存放函数体的二进制代码 . ) 只读数据段(RO data, .rodata):只读数据段是程序使用的一些不会被改变的数据, 使用这些数据的方式类似查表式的操作, 由于这些变量不需要修改, 因此只需放在只读存储器中. 已初始化读写数据段(data segment, .data段):通常是用来存放程序中已初始化的全局变量的一块内存区域. 数据段属于静态内存分配. 常量字符串就是放在这里的, 程序结束后由系统释放(rodata—read only data). 已初始化读写数据段(RW data, .data):已初始化数据是在程序中声明, 并且具有初值的变量, 这些变量需要占用存储器空间,

写壳2

≡放荡痞女 提交于 2019-11-28 16:40:32
壳2 创建MFC-基于对话框项目。 绘制界面 图片插入,添加工具-picture control-属性 属性-设置 一键加壳按钮实现 void CMFCShellDlg::OnBnClickedButton1(){ //设置过滤器 TCHAR szFilter[] = _T("文本文件(*.txt)|*.txt|所有文件(*.*)|*.*||"); // 构造打开文件对话框 CFileDialog fileDlg(TRUE, _T("txt"), NULL, 0, szFilter, this); CString strFilePath, strText;​ // 显示打开文件对话框 if (IDOK == fileDlg.DoModal()) { strFilePath = fileDlg.GetPathName(); //获取文件路径 CMyPack MyPack;​ // 读取一个 PE 文件 USES_CONVERSION; MyPack.LoadFile(W2A(strFilePath.GetBuffer()));​ // 读取 stub 文件 MyPack.LoadStub("my_stub.dll");​ // 将 stub 中的 .text 拷贝到 pe 文件的 .mypack MyPack.CopySection(".mypack", ".text");​ //

内存管理

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-28 15:44:00
内存管理 内存基本知识 什么是内存,有何作用 内存:存放数据 程序执行前需要先放到内存中才能被CPU处理--缓和CPU与硬盘之间的速度矛盾 内存地址,内存单元 进程运行的基本原理 指令的工作原理 操作码+若干参数 逻辑地址vs物理地址 程序经过编译、链接后生成的指令中指明的地址是逻辑地址(相对地址)相对于进程的起始地址而言 如何实现地址转换 装入的三种方式 绝对装入:在编译时,如果知道程序将放到内存中的那个位置,编译程序将产生绝对地址的目标代码 装入程序按照装入模块中的地址,将程序和数据装入内存 绝对装入只适用于单道程序环境 灵活性差 静态重定位:又称可重定位装入。编译、链接后的装入模块地址都是从0开始的,指令中使用的地址、数据存放的地址都是相对于起始地址而言的逻辑地址。 可根据内存的当前情况,将装入模块装入到内存的适当位置 装入时对地址进行“重定位”,将逻辑地址变换为物理地址(地址变换是在装入时一次完成的) 静态重定位的特点是在一个作业装入内存时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能装入该作业 运行期间就不能再移动 动态重定位:又称动态运行时装入。编译、连接后的装入模块的地址都是从0开始的。装入程序把装入模块装入内存后,并不会立即把逻辑地址转换为物理地址,而是把地址转换推迟到程序真正要执行时才进行。 装入内存后的地址依然是逻辑地址