进程和程序
程序包含的信息1. 二进制格式标识,现在大多是UNIX实现采用deELF格式
2. 机器语言指令
3. 程序入口地址(一般包含输入参数和环境变量)
4. 数据:程序文件包含的变量初始值和程序使用的字面常量
5. 符号表以及重定位表
6. 共享库和动态链接信息
7. 其他信息
从内核角度看,进程由用户内存空间和一系列内核数据结构组成,其中用户内存空间包含了程序代码以及代码所使用的变量,而内核数据结构则适用于维护进程状态信息。记录在内核数据结构中的信息包括许多与进程相关的标识号(ids), 虚拟内存表、打开文件描述符表、信号传递以及处理的有关信息、进程中源使用以及限制、当前工作目录和其他信息
点击(此处)折叠或打开
-
#include <unistd.h>
-
pid_t getpid(void);
-
/*always successfully returns process ID of caller*/
-
pid_t getppid(void);
- /*always successfully returns process ID of parent of caller*/
进程内存布局
每个进程所分配的内存由很多部分组成,通常称之为段(segment)1. 文本段包含进程运行的机器语言指令,只读,可共享
2. 初始化数据段包含显式初始化的全局变量和静态变量。
3. 未初始化数据段(BSS段),包含了未进行显式初始化的全局变量和静态变量。程序启动之前,系统将本段内所有内存初始化为0
4. 栈,是一个动态增长和收缩的段,由栈帧组成
5. 堆,是可在运行时动态进行内存分配的一块区域
虚拟内存空间
空间局部性(spatial locality):程序倾向于访问在最近访问过的内存地址附近的内存时间局部性(Temporal locality):程序倾向于在不久的将来再次访问最近刚刚访问过的内存地址
正是由于上述两种特性,使得程序即便仅有部分地址空间位于RAM当中,依然可能得以执行
程序当中在内存中驻留的页叫驻留集(resident set),未使用的页拷贝保存在交换区(swap area)——磁盘中的保留区域,作为计算机RAM的补充
在进程虚拟地址空间中,并非所有的地址范围都需要页表条目
由于内核能够为进程分配和释放页(和页表条目),所以进程的有效虚拟地址范围在其声明周期中可以发生变化。可能场景如下:
1. 栈向下增长时超出之前曾达到的位置
2. 堆中分配或释放内存时,通过调用brk(), sbrk(), malloc()...来提升program break的位置
3. 共享内存时(shmat(), shmdt(), mmap(), munmap())
每个(用户)栈帧包括如下信息:
1. 函数实参和局部变量
2. 调用的链接信息,每当一个函数调用另一个函数时,会在被调用函数的栈帧中保存一些寄存器的副本,以便返回时恢复
环境列表
在c语言程序中,可以使用全局变量char **environ访问环境列表(C运行时启动代码定义了该变量并以环境列表位置为其赋值),environ和argv参数非常类似点击(此处)折叠或打开
-
#include <stdlib.h>
-
char *getenv(const char *name);
-
/*returns pointer to (value) string, or NULL if no such variable*/
-
int putenv(char *string);
- /*returns 0 on success, or nonzero on error*/
点击(此处)折叠或打开
-
#include <stdlib.h>
-
int setenv(const char *name, const char *value, int overwrite);
-
/*returns 0 on success, or -1 on error*/
-
int unsetenv(const char *name);
- /*returns 0 on success, or -1 on error*/
点击(此处)折叠或打开
-
#define _BSD_SOURCE /*or: #define _SVID_SOURCE*/
-
#include <stdlib.h>
-
int clearenv(void);
- /*returns 0 on success, or a nonzero on error*/
非局部跳转
点击(此处)折叠或打开
-
#include <setjmp.h>
-
int setjmp(jmp_buf, env);
-
/*returns 0 on initial call, nonzero on return via longjmp()*/
- void longjmp(jmp_buf env, int val);