Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。
本篇导航
0. 进程退出退出概念
一个进程在执行完毕时,会退出。但是执行完毕一定是按照我们预想的方式执行的嘛?显然不是的
进程退出时一般会分为以下这三种情况:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止.
我们将围绕这三个方面来谈论进程退出这一概念.我们如何分辨一个进程退出时是哪种状态呢?
我们可以通过进程退出码来判断.
例如:下面是一个我们刚学习C语言时的代码
#include<stdio.h>intmain(){printf("Hello World\n");return0;}
其中的return 0就是给上层函数返回值(当该进程结束时,其为进程退出码).他会存在 **$?**该环境变量中
我们可以通过echo命令来打印出上一次进程运行的退出码.
echo$?
也就是说,每一次进程的状态退出码会存入到 **
?
∗
∗
,
所以
∗
∗
?**,所以**
?∗∗,所以∗∗?**只能存储最近一次的进程退出码
1. 进程运行完毕
进程运行完毕可以根据结果正确与否来分为两种情况.
1.1 结果正确
例如之前演示的:
#include<stdio.h>intmain(){printf("Hello World\n");return0;}
我们收到0之后知道这段程序按照我们预想的方式进行运行了.所以我们并不用关心他为什么会正确(现实生活中也没有人会这么问).
我们更多时候关心的是,这个进程运行完毕,但是结果错误的原因.
1.2 结果错误
我们人为的规定,进程退出码为0时表示进程运行错误.那么进程退出码是其他时该如何确认是什么原因呢?
C中封装了一个strerr的函数.来解决这个问题.
传入参数为对应的错误退出码,返回值为系统中对这段退出码的描述.
我们来看看系统中的错误码描述有几种.
intmain(){for(int i=0;i<200;i++)printf("%d:%s\n",i,strerror(i));return0;}
总共有134个(0-133).其中,0号退出码表示进程正确执行完毕.
当一个进程结果错误的时候.进程往往会保存他的错误码,在errorno中.这是一个全局变量,同样也仅能存储最近一次错误是什么原因.
例如:
intmain(){char*p=(char*)malloc(10000000000*1000*1000*1000*4);if(p==NULL){printf("errno:%d,because : %s",errno,strerror(errno));return errno;}else{return0;}}
我们用malloc向内存申请一个空间.若p==NULL则说明申请失败了.我们就可以通过errno配合strerror读出其的错误信息.
2. 进程异常
进程异常的本质是进程收到了对应的信号而停止了进程.
大多时候,进程异常时代码是没有运行完成的.所以我们并不需要去关注他的退出码是什么.而是关注他的退出信号.
我们写一个一眼错的程序看看什么叫进程异常.
intmain(){int a=10;
a/=0;int*p=NULL;*p=10;return0;}
第一个是/0错误,第二个是段错误(访问了不属于自己的内存). 运行看看结果
我们打开之前的kill信号表
kill-l
这两个错误对应的信号是8号与11号.我们来看看是不是
先运行一个简单的监控程序
intmain(){while(1){printf("ing\n");sleep(1);}return0;}
和我们的预期是一样的
3. return()、exit()与_exit()
我们先来看看return与exit的关系
return 为退出当前的函数.
exit 为退出当前的进程.
也就是说如果在main函数中使用,这二者差别不大. 也就是return 0 与 exit(0)等价
如果在其他函数中使用,return 会返回到上一层函数中去,而exit会直接退出这个进程.
那么exit()与_exit()呢?
exit为C封装的库函数,而_exit为系统调用
我们观察一下这个程序
intmain(){printf("hello");exit(0);}
会发生什么呢?
那么,换成系统调用会发生什么呢?
intmain(){printf("hello");_exit(0);}
printf并不生效了,这是为什么呢?
因为效率原因,printf打印并不会直接输出,而是直接放入到对应的缓冲区当中
而exit会先清除缓冲区,调用析构等语言层面的事情做完.再去调用_exit完成系统内核层面的结束.
而_exit直接完成系统层面的结束了.
我们也可以得出一个结论该缓冲区肯定不在内核中.因为这样exit与_exit的差别就不大了.也就不会出现上面的情况
68)]
printf并不生效了,这是为什么呢?
因为效率原因,printf打印并不会直接输出,而是直接放入到对应的缓冲区当中
而exit会先清除缓冲区,调用析构等语言层面的事情做完.再去调用_exit完成系统内核层面的结束.
而_exit直接完成系统层面的结束了.
我们也可以得出一个结论该缓冲区肯定不在内核中.因为这样exit与_exit的差别就不大了.也就不会出现上面的情况
版权归原作者 ppeua 所有, 如有侵权,请联系我们删除。