程序加载与运行问题

1、程序如何运行:

在多道程序环境下,要是程序运行,必须纤维质创建进程。而创建进程的第一件事,便是将程序和数据装入内存。如何将一个用户源程序变为一个可以在内存中执行的程序,通常都要经过一下几个步骤:

首先是要编译,有编译程序将用户源代码编译成cpu可执行的目标代码,产生了若干个目标模块(若干程序段)

其次是链接,有链接程序将编译后形成的一组目标模块(程序段),以及他们所需要的库函数链接在一起,形成一个完整的装入模块。

最后是装入,由装入程序将装入模块装入内存。

2、程序的装入方式:绝对装入方式、静态地址重定位、动态地址重定位

(1)绝对装入方式

在编译时,就已经知道程序驻留在内存中的什么位置,即程序中的逻辑地址跟实际地址完全相同。

优点:CPU执行目标代码快

缺点:(1)由于内存大小限制,能装入内存并发执行的进程数大大减少。

(2) 编译程序必须知道内存的当前空闲内存和其地址,执行效率低下

   (3)绝对装入方式只适用于单道程序环境

(2)静态地址重定位

在目标代码装入内存的过程中完成,在程序开始运行前,程序中的指令和数据的各个地址均已完成重定位,即虚拟地址到内存地址的映射。地址变换通常在装入是一次完成,以后不在改变。

优点:无需硬件支持

缺点:(1)程序重定位之后就不能再内存中搬动了。

   (2)要求程序的储存空间是连续的,不能把程序放在若干个不连续的区域中。

(3)动态地址重定位

在每次访问内存单元前才将要访问的程序或数据地址变换为内存地址。

优点:一个程序由若干个相对独立的目标模块组成时,每个目标模块个装入一个存储区域,这些存储区域可以是不顺序相邻的,只要各个模块有自己对应的定位寄存器就行。

3、程序的连接

源程序进过编译后,可得到一组目标模块,在利用连接程序将这组目标模块连接,根据连接时间的不同,可将连接分为如下三种:

(1)静态连接:在程序运行之前,先将各目标模块及他们所需的库函数,连接成一个完整的装配模块,以后不再拆开。

(2)装入时动态链接:将用户编译后所得到的一组目标模块,在装入内存时,采用边装入边连接的连接方式。在装入一个目标模块时,若发生一个外部模块调用事件,将引起装入程序去找出相应的外部目标模块,并将它装入内存。

(3)运行时动态链接。这是指某些目标模块的连接,是在程序执行中需要该模块时,才对它进行的连接。在执行过程中,当发现一个被调用模块尚未装入内存时,立即由OS去找到该模块并将之装入内存,把它链接到调用者模块上。凡在执行过程中未被用到的目标模块,都不会被调入内存和被链接到装入模块上,这样不仅可加快程序的装入过程,而且可节省大量的内存空间。

时间: 2024-10-13 16:21:04

程序加载与运行问题的相关文章

C++手动加载CLR运行托管程序(CLR Hosting)

转载自:http://www.linuxidc.com/Linux/2012-10/72293.htm 机制介绍 有些时候主程序是通过C/C++实现的,但是我们希望通过托管代码来扩展非托管程序,从而也获得托管代码带来的一系列优点.比如开发效率高,自动垃圾回收等. 运行托管与非托管代码根本区别在于托管代码是进程首先加载CLR然后通过CLR运行托管程序,而非托管代码则是操作系统直接根据其PE Header加载程序分配内存从而运行.因此如果需要通过托管代码来扩展非托管程序,首先要加载CLR来使非托管程

无法为具有固定名称“System.Data.SqlClient”的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类型“System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer”。请确保使用限定程序集的名称且该程序集对运行的应用程序可用。有关详细信息,请参阅 http://go.m

Windows服务中程序发布之后会如下错误: 无法为具有固定名称"System.Data.SqlClient"的 ADO.NET 提供程序加载在应用程序配置文件中注册的实体框架提供程序类型"System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer".请确保使用限定程序集的名称且该程序集对运行的应用程序可用.有关详细信息,请参阅 http://go.microsoft.com

32位汇编第二讲,编写窗口程序,加载资源,响应消息,以及调用C库函数

32位汇编第二讲,编写窗口程序,加载资源,响应消息,以及调用C库函数 (如果想看所有代码,请下载课堂资料,里面有所有代码,这里会讲解怎么生成一个窗口程序) 一丶32位汇编编写Windows窗口程序 首先我们知道32位汇编是可以调用Windows API的,那么今天我们就调用windowsAPI来写一个窗口程序 如果你有windows开发知识,那么就很理解了,如果没有,那么跟着我写,跟着步骤去写,那么也可以写出来 首先我们要编写一个窗口程序(使用SDKAPI编写)有几个步骤 1.设计窗口类 2.注

小白学phoneGap《构建跨平台APP:phoneGap移动应用实战》连载四(使用程序加载事件)

在了解了PhoneGap中都有哪些事件之后,本节将开始对这些事件的用法进行详细地介绍.本节要介绍的是程序加载事件,也就是deviceready.pause和resume这3个事件. [范例4-2 程序加载事件的使用] 01 <!DOCTYPE html> 02 <html> 03 <head> 04 <meta charset="utf-8"> 05 <title>程序加载事件的使用</title> 06 <

Linux进程启动过程分析do_execve(可执行程序的加载和运行)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-06 Linux-4.5 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.

MFC程序加载DLL文件时运行到Loadlibray()语句就无法继续下去

我在学习Detour时,为了进行测试,就建立了一个DLL文件和一个MFC工程. 但是我的MFC程序加载DLL文件时运行到Loadlibray("XXX.dll")这条语句就无法继续下去,没有报错,VS2010也没有停止,还是处于编译运行状态. 可是我之前加载的别的DLL文件都可以运行,这应该是很简单的加载DLL文件的过程呀,就想是dll文件的代码错误?或是MFC工程错误?还是Dll工程错误? 于是 我就将dll内的代码 复制到原来可以运行的DLL文件中发现可以运行,那就是代码没错, 接

Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)

execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.19后进入内核) syscalls,x86: Add execveat() system call exec()函数族 exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,

【Hight Performance Javascript】——脚本加载和运行

脚本加载和运行 当浏览器遇到一个<script>标签时,无法预知javascript是否在<p>标签中添加内容.因此,浏览器停下来,运行javascript代码,然后继续解析.翻译页面. 浏览器必须首先下载外部文件的代码,这要占用一些时间,然后解析并运行代码,这又要占用一些时间.此过程中,页面解析和用户交互是被完全阻塞的. 将脚本放在底部 合并脚本减少个数 延迟脚本(defer) <script src="file1.js" defer></s

未能加载文件或程序集“BLL”或它的某一个依赖项。生成此程序集的运行时比当前加载的运行时新,无法加载此程序集。

今天使用VS2012创建项目的时候,考虑到项目中代码的重用性以及清晰简洁性,搭建了一个三层架构,但是在项目运行的时候,总是报错: “未能加载文件或程序集“BLL”或它的某一个依赖项.生成此程序集的运行时比当前加载的运行时新,无法加载此程序集.” 在网上查找了半天也没有更好的办法,突然,灵感一现,修改.net版本,果断解决这个问题, 一开始是使用的版本是3.5:修改后的版本是:4.5 修改方法: 项目=>右键=>属性=>目标 framework=>选择版本