2011年(17)
分类: LINUX
2011-12-13 19:31:06
进程和程序的区别
程序是一个或多个文件,通常也叫做程序文件。这些文件包含了很多描述如何在运行时产生进程的信息。而进程是可执行程序的一个实例(内核会分配相应的数据结构来管理这个进程和它拥有的资源),一个可执行程序能产生很多个相同的进程。
可执行程序通常包含以下几部分信息:
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 char etext, edata, end;
printf(“%x\n”, &etext);
进程ID
每个进程在系统中都有一个独一无二的ID。
pid_t getpid(void)
注意点:
1.pit_t被定义为一个整型。这跟线程的pthread_t不同。
2.在linux内核中,进程ID有一个最大数。在linux2.6中,可以在/proc/sys/kernel/pid_max查看和修改。
进程父ID
pid_t getppid(void)
1.可以使用pstree命令来查看系统中的“进程树”。
2.进程的父ID可以通过查看/proc/PID/status中的Ppid字段查看。