分类: LINUX
2013-06-15 18:08:01
进程和程序的区别
程序是一个或多个文件,通常也叫做程序文件。这些文件包含了很多描述如何在运行时产生进程的信息。而进程是可执行程序的一个实例(内核会分配相应的数据结构来管理这个进程和它拥有的资源),一个可执行程序能产生很多个相同的进程。
可执行程序通常包含以下几部分信息:
1、文件格式信息。这些信息是告诉内核这是什么文件,该怎么来操作这个文件。在Linux上,有很长一段时间是使用a.out(assembler output)格式来格式化可执行文件。现在已经由elf(executable and linking format)格式取代。
2、机器语言。包含了程序要运行的代码。
3、数据。包含了用来初始化变量的数据和一些不变的字符串。(比如使用printf(“I am a programmer”).其中“I am a programmer”就是一个不变的字符串,它被存储在程序文件中的某个位置上)。
4、程序的入口地址。告诉内核从什么地方执行该程序。
5、符号和重定向表。
6、共享库和动态链接信息。包含了该程序要使用的共享库和链接该共享库链接器的路径名称。
7、其他信息。
进程的虚拟内存布局(所有的进程看到的都是连续的4G内存):
1、Text Segment。该段包含了该进程要运行的机器指令。为了防止错误指针破坏指令,系统把该段指定为“只读”。系统还把该段设置为可共享的,让多个运行着相同程序的进程共享同一个Text Segment,节约内存。
2、Initialized Data Segment。该段包含了显式初始化的全局变量(Global Variables)和静态变量(Static Variables)。这些变量都是在程序被加载进内存时从可执行文件中读取的。
3、Uninitialized Data Segment。该段包含了未被初始化的全局变量和静态变量。在程序运行前,系统会把该段中的数据全部初始化为0。通常我们把该段叫做BSS Segment(Block Started by Symbol)。为什么要把初始化了的全局变量和静态变量和未初始化的分开呢?主要原因是在程序被存储在硬盘上时,对于未初始化的变量,我们只需要记录地址和大小,而不需要记录它的初始值,节约硬盘空间和加载速度。
4、Stack Segment。函数调用栈。
5、Heap Segment。动态分配内存的地方。
可通过size命令来查看各段的大小。
在大部分的UNIX系统中,提供了etext,edata和end(如上图)这几个全局变量。我们可以用下面示例代码段,来获得不同段的终止地址。
extern int etext, edata, end;
printf(“%x\n”, &etext);