前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【Linux系统编程】六、进程终止

【Linux系统编程】六、进程终止

作者头像
利刃大大
发布2025-02-13 09:49:00
发布2025-02-13 09:49:00
12900
代码可运行
举报
文章被收录于专栏:csdn文章搬运csdn文章搬运
运行总次数:0
代码可运行

Ⅰ. 认识退出码

一、什么是退出码

​ 为什么 main 函数中,总是 return 0,如果我们 return 其它值可以吗 ❓

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
int main()
{
    return 0;
}

​ 答案是肯定可以!对于 main 函数的返回值,我们称之为 进程退出码,它代表进程退出后,结果是否正确!

​ 通常进程退出码为 0 代表成功,非0 则代表其它含义,如果你愿意你也可以 return 其它值。大部分情况下,main 函数跑完后,默认结果是正确的,所以我们以前返回的都是 0

所以这里给的建议就是如果未来我们的程序中比较关心进程的退出码的时候,那么要返回特定的数据表明特定的错误信息;而如果不必关心进程退出码的话,我们直接 return 0 即可!

​ 🔴 值得注意的是,这个退出码只记录最近一个进程在命令行中执行完毕时对应的退出码

二、如何查看退出码

main 函数 return 的值是给谁看的呢?那肯定不用说,因为是系统调用的 main 函数,那肯定是返回给系统(系统如何调用的我们后面会讲),以此来判断进程执行后的结果!

​ 这里又要引入一个新的环境变量: ? ,一般查看时候我们要配合 echo 进行打印使用,也就是 echo ?

​ 假设我们写一个程序最后 return 250,看看它的结果怎么样:

​ 结果就是 250 啦,但是有没有发现很奇怪,就是第二次和第三次调用 echo $? 的时候这个退出码已经变成 0 了,这是为啥 ❓❓❓

​ 其实很简单,因为 echo 也是一个指令,既然是指令那么肯定就是会创建一个子进程,这个子进程也会有退出码返回的,所以 我们每次打印的其实是最近一次的退出码(当然 echo 这种指令属于内建指令,比较特殊,后面会讲)

三、如何查看错误信息

​ 还记得我们在 C 语言中学到的一个函数 strerror() 吗,它就是用来**打印错误信息**的,它大概有 134 种标识!

​ 它的函数声明如下:

代码语言:javascript
代码运行次数:0
复制
#include <string.h>
char* strerror(int errnum);

​ 下面我们写个程序调用 strerror() 来查看一下全部的错误信息:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
#include <string.h>
int main()
{
    for(int i = 0; i < 134; ++i)
    {
        printf("num[%d]:%s\n", i, strerror(i));
    }
    return 0;
}

运行结果:
num[0]:Success
num[1]:Operation not permitted
num[2]:No such file or directory
num[3]:No such process
num[4]:Interrupted system call
......
num[129]:Key was rejected by service
num[130]:Owner died
num[131]:State not recoverable
num[132]:Operation not possible due to RF-kill
num[133]:Memory page has hardware error

​ 可以看到不同的错误码对应的出错误信息!

​ 接下来我们在命令行故意写错指令,看看报的是什么错误:

Ⅱ. 进程退出的情况

我们的进程只可能出现以下三种情况,不可能再出现其它的可能:

  1. 代码运行完毕,结果正确,退出码为 0
  2. 代码运行完毕,程序没有崩溃,但因为逻辑问题,结果不正确,退出码为 非0
  3. 代码没有运行完毕,程序非正常结束(比如野指针、越界等操作,包括人为 ctrl+c 或除 0 错误终止)此时退出码没有意义。

一般来说退出码在第二种情况下才起作用

Ⅲ. 进程常见的退出方法

一、正常退出

  • 在主函数中 return (注意非主函数中 return 只是返回值而不是退出程序!)
  • 调用用户级别函数 exit()
  • 调用系统级别函数 _exit()

对于后两个方法,我们在下面会详细的讲!

二、异常退出

​ 比如 ctrl + c,进程通过接收到信号而终止!

三、exit() 与 _exit()

① exit()

​ 我们在 C/C++ 中也经常看到这个函数,一般用于我们进程的不正确结果的退出,在非主函数中也是直接退出进程的

​ 下面来看看它的函数声明:

代码语言:javascript
代码运行次数:0
复制
#include <stdlib.h>
void exit(int status);
// 作用:任何函数 exit,都表示直接终止进程。
// 参数:status定义了进程的终止状态,父进程通过wait来获取该值
// 说明:虽然status是int,但是仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值是255。

​ 至于上面的参数 status,我们目前只需要知道它是退出码即可,它主要是和我们后面学的进程等待部分有关系,后面会讲!

​ 当 exit(-1) 时,结果如下:

代码语言:javascript
代码运行次数:0
复制
[liren@VM-8-2-centos process]$ make
gcc -o mypro proc.c -std=c99 
[liren@VM-8-2-centos process]$ ./mypro 
[liren@VM-8-2-centos process]$ echo $?
255
② exit() 与 _exit() 的区别

_exit() 是系统提供的接口,它的原型同库里的 exit 函数,函数的声明如下:

代码语言:javascript
代码运行次数:0
复制
#include <unistd.h>
void _exit(int status);

​ 其实本质上因为 _exit() 是系统级别的接口,所以 exit() 其实就是去调用的 _exit(),只不过要多做了一些工作,所以会有一些细节上面的差别,比如说下面这些工作:

  • 执行用户通过 atexit()on_exit() 定义的清理函数
  • 关闭所有打开的流,所有的缓存数据均被写入
  • 调用 _exit()

总结下来它们两者的差别如下:

  • exit() 在退出时与默认的 return 一样,会进行后续资源处理,包括刷新缓冲区
  • _exit() 在退出时,不会进行后续资源处理,直接终止进程

​ 写个代码展示一下它们的区别:

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    printf("running ...");
    sleep(3);
    
    // 比较两者的区别
    exit(1);
    // _exit(1);
    
    printf("done ...");
    return 0;
}

四、如果 main 函数里都不写 return 和 exit,退出码是啥 ❓

​ 理论上这里的退出码是未定义的、随机的,但实际上得到的退出码是 0,因为你的 main 函数里总会调用其它函数,成功后,遗留的历史数据是会充当返回值去返回的。

代码语言:javascript
代码运行次数:0
复制
#include <stdio.h>
int main()
{
    printf("hello world");
}

运行结果:
[liren@VM-8-2-centos process]$ ./mypro 
hello world[liren@VM-8-2-centos process]$ echo $?
0

main 函数里啥也不做,可以看到退出码依旧是 0,不必太纠结,这个本就是标准未定义的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Ⅰ. 认识退出码
    • 一、什么是退出码
    • 二、如何查看退出码
    • 三、如何查看错误信息
  • Ⅱ. 进程退出的情况
  • Ⅲ. 进程常见的退出方法
    • 一、正常退出
    • 二、异常退出
    • 三、exit() 与 _exit()
      • ① exit()
      • ② exit() 与 _exit() 的区别
    • 四、如果 main 函数里都不写 return 和 exit,退出码是啥 ❓
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档