个人主页:Lei宝啊
愿所有美好如期而遇
退出码
我们将main函数的返回值叫做进程的退出码。
我们使用echo $?可以查看进程最近一次执行情况的退出码。
修改main函数返回值,退出码也就改变了。
我们一般用0表示进程执行成功,其他数字表示进程执行失败,并且不同的数字代表着不同的失败原因,我们需要将错误码转换成错误描述,可以使用系统或者函数自带的方法进行转化,或者我们自定义。
在linux上我们可以看到134个错误码,同时我们也可以看到不同的错误码对应着不同的错误原因
接下来我们试着自己自定义。
错误码
函数有返回值,调用函数,我们通常想看到两种结果:
- 函数执行结果: 函数执行完毕后返回给调用者的值
- 函数执行情况:成功?失败?是执行过程中的一个状态
比如加法函数,执行结果就是返回计算的值,执行情况就是函数执行成功或者失败。
比如printf函数,执行结果就是输出及其返回值,执行情况就是是否执行成功。
并且我们这里想说明的是,main函数的返回值代表的是退出码,main函数结束代表进程结束,而其他函数结束仅仅只是这个函数结束。并且我们想得到函数的错误码,也只能通过errno获取库函数的错误码,自定义的函数不能通过errno去获取。
我们最终想说的结论就是,进程退出的场景只有三种:
- 进程执行成功,返回结果正确。
- 进程执行成功,返回结果错误。
- 进程出异常,未执行成功。
前两个我们是能理解的,第三个我们如何理解呢?
其实进程异常就是收到了异常信号,我们来演示一下。
我们从第一张图就知道,除0操作必然会导致进程异常退出,结果也的确是这样,我们向进程发送8号新号,一个死循环进程退出时,异常与除0操作相同,至此,我们也就明白进程异常本质就是收到了信号,而我们每一个信号都有编号,不同的信号编号表明了进程异常的原因。
任何进程的执行情况,我们也就可以用两个数字表明
- signnumber exitcode
- 0 0
- 非0 0
- 0 非0
- 非0 非0
而第二种和第四种其实属于一种情况,也就是进程异常,退出码其实也就不重要了。
我们接着介绍两个可以使进程退出的函数,一个系统调用,一个是C语言库函数。
他们有什么区别呢?
没有计算出结果,直接结束进程。
我们发现是一样的。
我们现在再来看看他们的区别
先休眠了一秒,然后全部打印。
我们发现什么都没有输出。
我们就能够明白这是因为缓冲区刷新的问题,exit会刷新缓冲区,而_exit不会。
同时我们也就能够明白这个缓冲区时不在操作系统管理下的,如果被操作系统所管理,那么一定会刷新,因为操作系统要保证效率,他不可能将数据写入缓冲区后不去输出。
我们推荐使用exit,因为_exit是linux下的系统调用,只能在linux下使用,而exit是封装过的,他就封装有_exit。我们说进程由操作系统所管理,也只有操作系统可以终止,现在操作系统给用户提供了终止进程的系统调用,用户也就可以使用他终止进程,而_exit如果我们使用的话,本平台的确不会有问题,但可能不能跨平台使用,而exit里面封装的终止进程的系统调用,在不同平台的C标准库下,都是不同的,但用户不用去理会,不用去关心系统调用,直接使用exit就可以了,这也就是跨平台性和可移植性。