Linux | 进程控制(上):进程终止(strerror函数、errno宏、_exit() 与 exit())

进程控制

1、进程终止

1.1进程常见退出方法

进程退出场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码异常终止

正常终止(可以通过echo $?查看进程退出码)

1.从main返回

2.调用exit

3._exit

异常退出:

  • ctrl + c,信号终止
退出码

当异常退出时,可以用return的不同的返回数字,表征不同的出错原因,即退出码

在正常写一个C/C++程序的时候,经常使用return 0;,但是在多进程的环境中,return的值就有讲究了。

1.1.1 strerror函数 & errno宏

strerror

头文件#include<string.h>

返回值:指向描述error errnum的错误字符串的指针,简单来说可以将退出码和对应的错误对应上。

举例:

#include<string.h>
int main()
{
	for(int i=0;i<10;i++){
        printf("%d: %s\n",strerror(i));
    }
    return 0;
}

效果如下,后面输出的就是退出码对应的错误描述:

errno

头文件#include<errno.h>

简单的说,errno会返回最后的一次错误码,使用errno可以获得退出码,通过返回退出码,在多进程中也可以让父进程知道子进程的状况。

注意:但是当进程异常退出的时候,本质可能就是代码没有跑完,那么进程的退出码就无意义了,所以应该要先看进程退出的时候,如果要关心进程的推出情况,要先关心退出时后有没有出异常,如果没有异常,再看结果是否正确,然后关心退出码。


  • 父进程关心子进程的退出,只需要确定:
    1. 父进程是否收到来自子进程的信号,若没有,说明没有异常,代码正常跑完
    2. 查看退出结果:0表示成功,非0表示错误,对应各自的原因

举例:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<errno.h>

int main()
{
    int ret = 0;
    char *p = (char*)malloc(1000*1000*1000*4);
    if(p==NULL){
        printf("malloc error, %d: %s\n".errno,strerror(errno));
        ret = errno;
    }   
    else{
        printf("malloc success\n");
    }   
    return ret;
}
1.1.1 _exit函数

头文件#include<unistd.h>

函数格式void _exit(int status);

_exit函数最后也会调用exit,但是在调用exit之前,还会做以下工作:

1、执行用户通过atexiton_exit定义的清理函数

2、关闭所有打开的流,所有的缓存数据均被写入

3、调用_exit

例1:

int main()
{
    printf("hello linux\n");
    exit(12);
}

或者:

int main()
{
    printf("hello linux\n");
	return 12;
}

编译执行完后再使用echo $?查询退出码,效果均如下:

区别在于:exit在任意地方被调用,都表示调用进程直接退出,如果调用的是return,只表示当前函数返回,原进程继续运行,如果调用一个含exit或者return的函数,就可以明显观察到。

_exit和exit的区别
结合现象分析:
int main()
{
    printf("hello world");
    sleep(1);//使用sleep能够观察到一些现象,下文会提及
    exit(11);
}

运行完毕后再调用echo $?查看退出码,效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

但是将exit改为_exit后:

int main()
{
    printf("hello world");
    sleep(1);
    exit(11);
}

运行完毕后再调用echo $?查看退出码,效果如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

原因

当代码中输出的内容以\n结尾时,当代码运行到printf这条语句时,程序会直接输出内容,但是如果没有以\n结尾,那么就会先将内容存到缓冲区中,当程序结束前会冲刷缓冲,关闭流,然后就有打印输出的效果,也正因此会发现运行的时候是先等待了一秒钟,输出句子后程序马上结束,而不是先输出句子,等待一秒钟再结束程序。


结合下图

  • 调用exit()后会先执行用户定义的清理函数,再冲刷缓冲,关闭流等,因此会有打印字符串的效果,最后再调用_exit系统调用
  • _exit()是一个系统调用接口,调用_exit()后,其会在操作系统内部直接终止进程,对应缓冲区的数据不做刷新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值