Linux - 进程 - 进程终止

一. 进程退出场景

  • 进程正常终止, 结果正确.

  • 进程正常终止, 结果不正确.

  • 进程异常终止.

二. 进程正常终止

从 main 返回

C 程序总是从 main 函数开始执行, main 函数的原型是:

但实际上 main 函数只是用户程序的入口, 当内核执行 C 程序时(使用一个 exec 函数), 在调用 main 前先调用一个特殊的启动例程. 可执行程序文件将此启动例程指定为程序的起始地址. 启动例程从内核取得命令行参数和环境变量值, 然后为按上述方式调用 main 函数做好准备.

从 main 函数 return 是一种常见的进程终止方法. 启动例程使得 main 返回后立即调用 exit(), 在 main 中执行 return n 等同于执行 exit(n), 因为调用 main 的启动例程会将 main 的返回值当做 exit() 的 status 参数. 如果将启动例程以 C 代码形式表示 (实际上该例程常常用汇编语言编写), 则它调用 main 函数的形式可能是:

通过如下一段代码对上述描述进行验证.

c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
    printf("hello world\n");
    return 0;
}

当运行生成的可执行程序后, 使用 echo $? 打印最近一次进程的退出码, 为 0, 说明该进程确实正常终止了. 在 Linux 中, 0 通常表示成功, 非 0 值表示失败.

进程退出码

C 库中的 strerror 可以通过错误码, 获取对应的错误信息.

c 复制代码
#include <stdio.h>
#include <string.h>

int main()
{
    int i = 0;
    for ( ; i < 134; i++) {
        printf("%d:%s\n", i, strerror(i));
    }
    return 0;
}

当运行生成的可执行程序后, 就可以看到各个错误码所对应的错误信息.

注意: 退出码都有对应的错误信息, 帮助用户确认程序执行失败的原因, 而这些退出码具体代表什么含义是人为规定的, 不同环境下相同的退出码的错误信息可能不同.

_exit()

_exit() 会直接终止进程, 并不会在退出进程前会做任何收尾工作.

c 复制代码
#include <stdio.h>
#include <unistd.h>

int main()
{
    printf("hello world");
    _exit(1);
}

以上代码中使用 _exit() 终止进程, 缓冲区当中的数据将不会被打印到显示屏上.

exit()

使用 exit() 终止进程是常用的方法, exit() 可以在任何地方终止进程, 并在终止进程之前会做一系列工作:

  1. 调用任何由 atexit() 或 on_exit() 注册的函数, 和在系统中注册时顺序相反.

  2. 清空并关闭所有已经打开的标准 I/O 流 (此过程将所有被缓冲但还没有被写出的数据写出).

  3. 删除由 tmpfile() 函数创建的所有临时文件.

这些步骤完成了在用户空间需要做的所有工作, 最后 exit() 会调用系统调用 _exit(), 内核可以处理终止进程的剩余工作.

对以下代码进行测试.

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    printf("hello world");
    exit(2);
}

运行结果如下.

三. 进程异常终止

进程一般由于接到一个信号而异常终止, 后期谈论进程信号时再谈论这一话题.

四. exit() 与 _exit() 中的 status

对如下一段代码进行测试.

c 复制代码
#include <stdio.h>
#include <stdlib.h>

int main()
{
    exit(-1);
    return 0;
}

当运行生成的可执行程序后, 使用 echo $? 打印最近一次进程的退出码, 发现其为 255, 而非 -1.

出现这样的现象, 是因为父进程通过 wait() 来获取子进程的退出码 时 status 仅有低 8 位可以被父进程所用.

以上面那一段代码为样例进行说明: 对于无符号整型来说, 数据以补码的形式存放在内存中, 所以 status 的二进制表示为 11111111 11111111 11111111 11111111, 而 0377 的二进制表示为 11111111, 两者按位与的结果即为 11111111, 表示为十进制即为 255, 所以使用 echo $? 打印最近一次进程的退出码, 其值为 255, 而非 -1.

相关推荐
tongsound19 分钟前
libmodbus 使用示例
linux·c++
拾光Ծ21 分钟前
【Linux】“ 权限 “ 与相关指令
linux·运维·服务器
硬核子牙24 分钟前
调试器是怎么让代码停下来的
linux
To_再飞行24 分钟前
Linux Bash(一)
linux·运维·服务器·bash
LCG元38 分钟前
保姆级教程:CentOS 7/8 部署Nginx + MySQL + PHP(LEMP)环境,从零开始到上线项目
linux
疯癫的老码农1 小时前
【Linux环境下安装】SpringBoot应用环境安装(五)-milvus安装
linux·spring boot·milvus
孤廖1 小时前
C++ 模板再升级:非类型参数、特化技巧(含全特化与偏特化)、分离编译破解
linux·服务器·开发语言·c++·人工智能·后端·深度学习
油条不卖1 小时前
本地window10同步ubuntu上conda指定环境,并在C#项目中通过Python.NET调用自定义python接口
linux·ubuntu·conda
6190083361 小时前
linux 安装jdk
java·linux·运维
waves浪游2 小时前
基础开发工具(中)
linux