进程终止的方式
正常的终止方式有:
- 从main返回
- 调用exit
- 调用_exit和_Exit
- 最后一个线程从其启动例程返回
最后一个线程调用pthread_exit
异常的终止方式有调用abort
- 接到一个信号并终止
- 最后一个线程对取消请求作出响应
_exit和exit的区别
由于历史原因,exit总是执行一个标准IO库的清理关闭操作,为所有的打开流调用fclose函数,并且调用atexit注册的回调函数。
_exit和_Exit则立刻进入内核。
atexit
int atexit( void (*func)(void));
其中,atexit的参数是一个函数地址。 进程最多可以设置32个exit清理函数。
## C程序的启动过程
见书图 7-1
内核使程序执行的唯一方法是调用exec函数。进程自愿终止的唯一方法是显示或者隐式的调用_exit或_Exit. 进程也可以非自愿的由一个信号使其终止。
## 环境表
大多数Unix系统都支持main函数的第三个参数,`char **env`. 这个变量保存了系统的环境变量。
#setjump和longjump函数
在C中,goto语句是不能跨越函数的。执行跨越函数的跳转功能的是函数setjmp和longjmp。这两个函数对于处理发生在深层次嵌套函数调用中得出错情况是非常有用的。
```cpp
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
jmp_buf是用来存放调用longjmp时,能恢复调用栈状态的必要信息。
在调用了longjmp之后,register和普通变量一般会保持longjmp这个地点的值。static,global和volatile变量一般保持setjmp时的值。这是因为 setjmp时,寄存器现场被保存下来,longjmp时寄存器被恢复。 static,global和volatile变量都在内存中,而register和普通变量一般会在寄存器中。