程序编译过程与软件启动过程

原创 2011年01月11日 10:58:00

一、      软件执行流程

1、 软件编译流程

Ø  预编译完成宏展开工作。

Ø  为每一个.cxx源文件编译一个目标文件(.obj,.o),目标文件中至少包含二进制的代码段和数据段。在cxx源文件中可能会引用在其他cxx/hxx中定义的符号,也可能是自己定义的一些符号,这些作用域超过一个cxx文件的符号称为“public符号”(例如非静态函数)。因此每一个目标文件中也包含一个符号表,用于记录自己引用的符号及自己提供的public符号。

Ø  编译器合成这些目标文件成一个库文件(.lib),同时解析可以找到的符号引用。此时这个库文件包含了二进制的代码段和数据段,同样也会包含一个符号表,因为有一些符号需要引用其他静态/动态链接库的导出符号。

Ø  链接器负责把目标的库文件和所有需要引用的静态/动态链接库进行链接,即需要首先把静态库合成到可执行文件中。转换相应的符号引用为地址,然后确保所引用的其他动态链接库的符号存在。最后生成可执行文件,可执行文件的符号表只需要记录导入符号表。

 

 

2、 软件运行流程

Ø  当双击App.exe图标启动程序时,执行起来的App进程是shell调用CreateProcess激活的。桌面上的带有小箭头的快捷方式(shortcut)就是一个shell链接,shell负责管理一个叫"名字空间"的类似文件系统似的“超文件系统”,它允许应用程序在任何地方在不知访问对象名字和位置的前提下访问到这个对象,此类对象有:文件,目录,驱动器,打印机以及网络资源。而名字空间就是shell把这些对象有层次组织起来的一个结构。名字空间为用户和应用程序提供了一种可靠和高效的方法来访问和管理对象。

 

Ø  CreateProcess函数被调用,系统创建一个“进程内核对象”。进程内核对象可以看作一个操作系统用来管理进程的内核对象,它是系统用来存放关于进程统计信息的地方(一个小的数据结构),真正创建者是NtCreateProcess的系统服务函数(也叫执行体服务函数),他创建了进程内核对象供用户扩展。进程内核对象的初始使用计数为1。然后系统为该进程创建4GB=2^32)的虚拟地址空间(所谓虚拟就不是真的创建4GB的物理内存空间,这些空间不是真在物理内存上).用于加载App.exe可执行文件和任何必要的dll文件的数据和代码。系统为该进程创建4GB的虚拟地址空间,对于windows来说,默认情况下每个用户进程可以占有2GB的私有地址空间;操作系统占有剩余的2GB空间。

    32x86系统上:

0x000000000x7fffffff的空间中存放着 应用程序代码,全局变量,每个线程堆栈,dll代码。
0x800000000xc0000000的空间中存放着内核和执行体,HAL(硬件抽象层),引导驱动程序。
0xc00000000xc0800000的空间中存放着进程页表和超空间。
0xc08000000xffffffff的空间中存放着系统高速缓存,分页缓冲池,非分页缓冲池。

 

Ø  CreateProcess打开应用程序文件(.exe),它先扫描该文件的文件头,该文件头里含有文件能运行在那个环境之下,如果是win32环境,系统就直接加载文件的代码和数据并输入(import)该文件执行所需的dll函数。如果不是win32环境比如是os/2.exe则先加载相应的环境子系统,再由该环境加载该文件的代码和数据以及该文件执行所需的dll函数。

    加载器负责把可执行文件的数据段和代码段映射到进程的虚拟内存空间中,读入可执行程序的导入符号表,然后根据这些符号表可以查找出该可执行程序所有依赖的动态链接库。

 

Ø  进程加载代码和数据完毕后,就开始创建线程来执行进程空间内的代码。进程是静态的,它只是线程的容器。一个进程至少因该有一个线程(main thread),其它线程都是主线程通过调用CreateThread函数创建的。线程也是核心对象,他的实际创建者是NtCreateThread系统服务函数。一个线程只是一个线程核心对象和两个堆栈(一个核心堆栈,用于线程运行在核心态;一个用户堆栈,用于线程运行在用户态),线程与进程类似,也拥有线程核心对象计数和线程句柄。线程用于描述进程中的运行路径。

   

Ø  每当进程被初始化时,系统就要创建一个主线程。该线程与c/c++运行时库的启动代码一道开始运行,启动代码则调用进入点函数(就是main函数,它也是主线程的进入点函数),并且继续运行直到进入点函数返回并且c/c++运行时库的启动代码调用ExitProcess为止。每个线程都有自己的入口点函数,主线程入口点函数名字必须是main,wmain,WinMainwWinMain.而其他的线程入口点函数名字可使用任何名字。每个线程函数必须有一个返回值,它将作为线程的退出代码。对于主线程来说,这个返回值将传给c/c++运行时库的启动函数。c/c++运行时库的启动函数是一个程序调用的第一个函数,它是在程序链接时由链接程序选择相应的启动函数并加到程序的开始处。c/c++运行时库有四个版本的启动函数,他们分别对应不同类型的应用程序。比如,需要ANSI字符和字符串的GUI应用程序的启动函数是WinMainCRTStartup,其对应的进入点函数是WinMain,需要Unicode字符和字符串的GUI应用程序的启动函数是wWinMainCRTStartup,其对应的进入点函数是wWinMain,而需要ANSI字符和字符串的CUI应用程序(如控制台console程序)的应用程序的启动函数是mainCRTStartup,对应的入口点函数为main;需要Unicode字符和字符串的CUI应用程序(如控制台console程序)的应用程序的启动函数为wmainCRTStartup,对应的入口点函数为wmainc/c++运行时库的启动函数(WinMainCRTStartup为例)的功能如下:
检索指向新进程的完整命令行指针;检索指向新进程的环境变量的指针;对c/c++运行时的全局变量进行初始化;对c运行期的内存单元分配函数(比如malloccalloc)和其他低层I/O例程使用的内存栈进行初始化。为C++的全局和静态类调用构造函数。

 

Ø  启动函数条用主函数,进入应用程序的执行。

 

Ø  当主函数执行完毕返回时,启动函数就调用c运行期的exit()函数,将返回值(nMainRetVal)传递给启动函数。之后exit()便开始收尾工作。

 

Ø  运行时启动函数调用操作系统的ExitProcess函数,将nMainRetVal传递给它,这使得操作系统能够撤销进程并设置它的exit 代码。

一个win32应用程序文件的启动过程

学习windows 编程从mfc角度来说可分为两部分那就是WinMain函数以前的,和WinMain函数以后的。前者涉及很多windows操作系统内部的知识,后者需要看mfc源码。虽然大多数程序不需要...
  • hczhiyue
  • hczhiyue
  • 2014年02月08日 19:17
  • 1287

iOS之应用程序启动过程及原理总结

当用户点击应用图标之后,应用就开始启动。应用启动完成后,就会展示一系列的视图,和用户进行各种各样的交互(如滑动、点击)。当用户退出应用后,该应用就无法和用户进行交互。这一过程就体现了一个应用的生命周期...
  • shxwork
  • shxwork
  • 2016年04月19日 18:04
  • 2416

机顶盒软件组成及启动流程

1.  软件结构组成     uboot        : 一种boot loader,负责机顶盒嵌入式linux的系统引导工作,引导系统启动,已经系统维护(镜像烧写,软件更新)。  ...
  • techelefeng
  • techelefeng
  • 2016年07月11日 23:09
  • 865

Linux用命令启动程序

安装了一个程序,想在终端里启动它,需要给它配置个环境 这里用Google浏览器作例子 安装好Chrome 在终端输入 chrome 提示:chrome:未找到命令 输入 sudo gedit ~/...
  • wu_wxc
  • wu_wxc
  • 2015年10月06日 13:45
  • 9176

Linux安装启动过程

1 开机后BIOS自检     由BIOS判断磁盘上有哪些引导程序之后加载     常见bootloader   –>   grub lilo syslinux/isolinux 2 由(bo...
  • code__L
  • code__L
  • 2016年08月29日 00:27
  • 730

STM8单片机的启动过程。

大学的时候,学过一学期的STM8单片机,当时也算下了挺大的功夫,用的是我挺佩服的一个老师的课本,是用汇编语言教的。不过佩服归佩服,这本书其实现在想起来,一些基础的东西讲得不是很明白,比如说第一章中讲单...
  • u010093140
  • u010093140
  • 2015年11月22日 23:18
  • 2044

如何让应用程序在计算机开机后延迟启动?

 通过Window计划任务可以设置应用程序开机后延时启动。 在程序列表中搜索“计划任务“。 打开计划任务,选择“创建基本任务“ ...
  • lordwish
  • lordwish
  • 2016年06月23日 13:27
  • 14120

解析STM32启动过程

相对于ARM上一代的主流ARM7/ARM9内核架构,新一代Cortex内核架构的启动方式有了比较大的变化。ARM7/ARM9内核的控制器在复位后,CPU会从存储空间的绝对地址0x000000取出第一条...
  • dddxxxx
  • dddxxxx
  • 2015年08月29日 11:53
  • 1036

软件安装过程解析

软件在安装时,到底做了些什么? 大家每天都在用电脑,可能也经常在自己的电脑上安装软件。就算自己没安装过,至少也看到人家安装过软件。在这里,我不是想教你怎么安装软件,而是想向你展示,软件在安装的过程中,...
  • zhyjunFov
  • zhyjunFov
  • 2014年03月21日 10:24
  • 1504

VC++编程中为程序加入启动画面功能

如何为自己的程序加入启动画面   观察我们平常使用的软件,当我们双击软件的时候,会在主界面出现前,先行出现一个启动画面,由于前一阵子写了一个基于对话框的程序,亲自实验了下,今天就为大家简单的介绍下,...
  • u014028070
  • u014028070
  • 2014年11月22日 12:26
  • 1729
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:程序编译过程与软件启动过程
举报原因:
原因补充:

(最多只允许输入30个字)