目录
什么是进程终止
进程退出的场景
退出码
0退出码
!0系统退出码
非0自定义退出码
进程的终止从三个方面去谈。清楚进程终止是在做什么?进程终止的3中情况?如何终止?注意进程终止不是进程暂停。
什么是进程终止
❓进程终止是在做什么
回答:释放曾经的代码和数据所占据的空间。释放内核数据结构。
理解:在上篇进程的创建我们知道OS创建进程是先创建内核数据结构,再加载代码和数据。所以终止进程我们要先把代码和数据所占的空间归还给OS,再释放内核数据结构。(PCB task_struct会延期处理,此时进程处于Z状态僵尸状态)
main函数return相当于进程终止了。
进程退出的场景
进程终止存在3种情况:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止
退出码
C/C++语言中main函数存在返回值return 0是什么意思❓为什么每次只写返回0呢❓可以换成其他值❓
- ./ 创建启动进程命令行中启动的所有进程都是bash的子进程
- 在bash的环境变量表中存在一个变量?变量名:?
- 查看这个环境变量echo $? (访问变量内容)
- ?里面是父进程获取到的,最近一个子进程的退出码。
- main函数return的值是退出码
- 0是成功
- !0是标识失败
- echo内建命令,但也是一个进程(用父进程执行的,没有创建新的子进程)
- 如果子进程执行任务成功退出码是0
- 如果子进程执行任务出现了失败是非0
- !0不同的非0值,一方面表示失败,一方面表示失败的原因(每一个都有对应的错误描述)
- 注意❗退出码表示的是代码是运行完毕,结果正确与否。
- 0:代码运行完毕,结果正确
- !0:代码运行完毕,结果不正确
理解:bash把任务交给子进程,在进程层面上,bash也需要知道任务执行的结果。(进程的退出码把子进程的退出结果给到父进程)
既然把子进程创建出来了,让父进程得到了进程退出信息,return值会通过一定方式让bash拿到(一定方式:进程等待)
Makefile
1 myprocess:myprocess.c
2 gcc -o $@ $^
3 .PHONY:clean
4 clean:
5 rm -f myprocess
myprocess.c
1 #include<stdio.h>
2 #include<unistd.h>
3 int main()
4 {
5 printf("I am process,pid: %d,ppid: %d\n",getpid(),getppid());
6 sleep(2);
7 return 100;
8 }
0退出码
代码运行完毕,结果正确。
!0系统退出码
!0:代码运行完毕,结果不正确
- !0不同的非0值,一方面表示失败,一方面表示失败的原因
- (每一个都有对应的错误描述)
- 🆗失败原因可以是由系统OS来制定,OS实现错误码和错误信息的描述转化。
- 查看退出码具体的系统的接口:man strerror
- 用strerror查看系统定义的错误码char *strerror(int errnum)传入错误码,返回错误码相对应的错误描述。(gcc myprocess.c -o myprocess -std=c99)每个错误码都有对应的错误描述string。
- 🆗失败原因也可以是由程序员自定义
- 父进程bash为什么要得到子进程的退出码呢?因为要知道子进程退出的情况,是成功/失败/失败的原因是什么?为了给用户负责。用户需要知道。
- 例如我们平时的指令也是一个可执行程序,这个可执行程序的也是存在返回码的。
- 子进程退出码(1.系统默认 2.用户自定义)----------→父进程------------→用户
myprocess.c
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<string.h>
4 int main()
5 {
6 for(int errcode = 0; errcode <= 225; errcode++)
7 {
8 printf("%d:%s\n",errcode,strerror(errcode));
9 }
12 }
非0自定义退出码
- 自定义退出码
- 结合退出码给出相应的退出描述
- 无论是系统的/自定义的退出码 最终退出码都会给到父进程的环境变量?
myprocess.c
1 #include<stdio.h>
2 #include<unistd.h>
3 #include<string.h>
4 //自定义枚举常量
5 enum
6 {
7 Success = 0,
8 Div_Zero,//1
9 Mod_Zero,//2
10 };
//自定义退出码不出错为0,出错为!0
11 int exit_code = Success;
//错误码对应定义错误描述
12 const char *CodeToErrString(int code)
13 {
14 switch(code)
15 {
16 case Success:
17 return "Success";
18 case Div_Zero:
19 return "div zero!";
20 case Mod_Zero:
21 return "mod zero!";
22 default:
23 return "unknow error!";
24 }
25 }
26 int Div(int x, int y)
27 {
28 if( 0 == y )
29 {
30 exit_code = Div_Zero;//修改错误码
31 return -1;
32 }
33 else
34 return x/y;
35 }
36 int main()
37 {
38 int result = Div(10, 100);
39 printf("result: %d [%s]\n", result, CodeToErrString(exit_code));
40 result = Div(10, 0);
41 printf("result: %d [%s]\n", result, CodeToErrString(exit_code));
42
43 return exit_code;
44 }
🙂感谢大家的阅读,若有错误和不足,欢迎指正。进程终止还有最后一种情况是代码异常终止。下篇进程信号和如何进程终止。