进程的启动
当内核执行C程序时(使用exec函数)在调用main前先调用一个特殊的启动例程。可执行程序文件将此启动例程指定位程序的起始地址。启动例程从内核取得命令行参数和环境变量值,然后为按上述方式调用main函数做好安排。
进程的终止
正常终止
- 从main返回
- 调用exit
- 调用_exit或_Exit
- 最后一个线程从其启动例程返回
- 从最后一个线程调用pthread_exit
异常终止
- 调用abort
- 接到一个信号
- 最后一个线程对取消请求做出响应
- 进程通过main函数return返回,会调用C库中的exit函数,exit函数首先调用各终止处理函数,然后关闭(通过fclose)所有打开流,然后调用的_exit退出。
- 如果直接调用_exit不会调用终止处理函数和关闭被打开的流。
- 若程序调用exec函数族中的任一函数,则将清除所有已注册的终止处理函数。
- 进程收到信号时,如果没有注册对应的信号处理函数,那么内核就会执行信号的默认动作,一般是直接终止进程。
1. 演示 return, exit, _exit 的区别
下面代码来源第5章 进程环境(2)_进程的启动和终止
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void term_fun1(void){
printf("first term function\n");
}
void term_fun2(void){
printf("second term function\n");
}
void term_fun3(void){
printf("third term function\n");
}
int main(int argc, char* argv[]){
if (argc < 3){
fprintf(stderr, "usage: %%s file[exit|_exit|return]\n");
exit(1);
}
atexit(term_fun1);
atexit(term_fun2);
atexit(term_fun3);
FILE *fp = fopen(argv[1], "w");
fprintf(fp, "hello world!\n");
if(!strcmp(argv[2], "exit")){
exit(0);
} else if (!strcmp(argv[2], "_exit")){
_exit(0);
} else if (!strcmp(argv[2], "return")){
return 0;
} else {
fprintf(stderr, "usage: %%s file[exit|_exit|return]\n");
}
return 0;
}
# return 调用终止处理程序,刷新标准I/O缓存
LEOQYANG-MC1:ch07 leoqyang$ ./process_term process_term.txt return
third term function
second term function
first term function
LEOQYANG-MC1:ch07 leoqyang$ cat process_term.txt
hello world!
# exit 调用终止处理程序,刷新标准I/O缓存
LEOQYANG-MC1:ch07 leoqyang$ ./process_term process_term.txt exit
third term function
second term function
first term function
LEOQYANG-MC1:ch07 leoqyang$ cat process_term.txt
hello world!
# _exit 不执行终止处理程序,不刷新标准I/O缓存,直接退出
LEOQYANG-MC1:ch07 leoqyang$ ./process_term process_term.txt _exit
LEOQYANG-MC1:ch07 leoqyang$ cat process_term.txt
LEOQYANG-MC1:ch07 leoqyang$
2. 演示收到信号的情况
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
static void callback(void){
printf("callback\n");
}
int main(int argc, char * argv[]){
if (argc < 2){
fprintf(stderr, "usage: filename\n");
exit(1);
}
FILE *fp = fopen(argv[1], "w");
fprintf(fp, "hello world!\n");
atexit(callback);
while(1) {
sleep(1);
}
printf("main exit\n");
return 0;
}
# 执行killall 3_3_2 不执行终止处理程序,不刷新标准I/O缓存,直接退出
LEOQYANG-MC1:ch3 leoqyang$ ./3_3_2 3_3_2.txt
Terminated: 15
LEOQYANG-MC1:ch3 leoqyang$ cat 3_3_2.txt
LEOQYANG-MC1:ch3 leoqyang$
参考
- 第5章 进程环境(2)_进程的启动和终止
- Unix环境高级教程 第7章
- Linux环境编程 第3章