[APUE]第七章 进程环境
第七章 进程环境
引言:
main函数是如何调用的
命令行参数是如何传送给执行程序的
典型的存储器布局是什么样式
如何分配另外的存储空间
进程如何使用环境变量
各种不同进程的终止方式
longjmp和setjmp
start
进程的终止
正常终止:
从return返回
调用exit
调用_exit、_Exit
最后一个线程从其启动例程返回
最后一个线程调用phread_exit
异常终止:
调用abort
接受一个信号终止
最后一个线程对取消请求作出反应
void exit(int status)
void _exit(int status)
void _Exit(int status)
exit函数总是执行一个标准I/O库的清理关闭操作,为所有打开的流调用fclose,执行各终止处理函数(atexit())
int atexit(void (*func) (void))
在进程即将退出的时候调用这些注册的清理函数,调用的顺序和注册的顺序相反。,并且如果你注册一个函数两次,那么就会调用终止处理函数两次。
环境表:
环境表就是一个字符指针数组,其中每一个指针包含一个以NULL结束的c字符串的地址。全局变量environ包含了该指针数组的地址
extern char** environ,
environ和main函数传进来的argv参数类似,2维最后一项都是NULL指针。
char * getenv(const char* name) //获取名为name的环境变量所对应的value,
int putenv(char* str) //add
int setenv(const char* name, constchar*value, int rewrite)//set
int unsetenv(const* name)//delete
其中:
putenv str是name=value的字符串格式,如果name已经存在,则删除原来的
setenv 是修改name所对应的value 如果rewrite为非0 name存在,则覆盖,如果rewrite为0,就不覆盖
unsetenv删除环境变量中key位name的值
c程序的存储空间布局
从历史上讲,C程序一直由下面几部分组成:
(1) 栈
由编译器自动分配释放管理。局部变量及每次函数调用时返回地址、以及调用者的环境信息(例如某些机器寄存器)都存放在栈中。新被调用的函数在栈上为其自动和临时变量分配存储空间。通过以这种方式使用栈,C函数可以递归调用。递归函数每次调用自身时,就使用一个新的栈帧,因此一个函数调用实例中的变量集不会影响另一个函数调用实例中的变量。
a.局部变量
b.函数调用时返回地址
c.调用者的环境信息(例如某些机器寄存器)
(2) 堆
需要由程序员分配释放管理,若程序员不释放,程序结束时可能由OS回收。通常在堆中进行动态存储分配。
如程序中的malloc, calloc, realloc等函数都从这里面分配。堆是从下向上分配的。
(3) 非初始化数据段
通常将此段称为bss段,这一名称来源于早期汇编程序的一个操作符,意思是“block started by symbol(由符号开始的块)”,未初始化的全局变量和静态变量存放在这里。在程序开始执行之前,内核将此段初始化为0。函数外的说明:long sum[1000] ; 使此变量存放在非初始化数据段中。
a.未初始化的全局变量
b.未初始化的静态变量
(4) 初始化的数据
通常将此段称为数据段,它包含了程序中需赋初值的变量。初始化的全局变量和静态变量存放在这里。例如,C程序中任何函数之外的说明:int maxcount = 99; 使此变量以初值存放在初始化数据段中。
a.初始化的全局变量
b.初始化的静态变量
(5) 正文段
CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是经常环境指针环境表环境字符串执行的程序(如文本编辑程序、C编译程序、s h e l l等)在存储器中也只需有一个副本,另外,正文段常常是只读的,以防止程序由于意外事故而修改其自身的指令。
int setjmp(jmp_buf env)
void longjmp(jmp_buf env, int value)
setjmp第一次调用初始化env,函数返回0,在longjmp中调用返回的时候,setjmp返回的是longjmp的value