【Linux】进程控制

img

Halo,这里是Ppeua。平时主要更新C语言,C++,数据结构算法…感兴趣就关注我吧!你定不会失望。


在这里插入图片描述

0. 进程退出退出概念

一个进程在执行完毕时,会退出。但是执行完毕一定是按照我们预想的方式执行的嘛?显然不是的

进程退出时一般会分为以下这三种情况:

  1. 代码运行完毕,结果正确
  2. 代码运行完毕,结果不正确
  3. 代码异常终止.

我们将围绕这三个方面来谈论进程退出这一概念.我们如何分辨一个进程退出时是哪种状态呢?

我们可以通过进程退出码来判断.

例如:下面是一个我们刚学习C语言时的代码

#include <stdio.h>
int main()
{
    printf("Hello World\n");
    return 0;
}

其中的return 0就是给上层函数返回值(当该进程结束时,其为进程退出码).他会存在 **$?**该环境变量中

我们可以通过echo命令来打印出上一次进程运行的退出码.

echo $?

也就是说,每一次进程的状态退出码会存入到 ** ? ∗ ∗ , 所以 ∗ ∗ ?**,所以** ?,所以?**只能存储最近一次的进程退出码

1. 进程运行完毕

进程运行完毕可以根据结果正确与否来分为两种情况.

1.1 结果正确

例如之前演示的:

#include <stdio.h>
int main()
{
    printf("Hello World\n");
    return 0;
}

我们收到0之后知道这段程序按照我们预想的方式进行运行了.所以我们并不用关心他为什么会正确(现实生活中也没有人会这么问).

我们更多时候关心的是,这个进程运行完毕,但是结果错误的原因.

1.2 结果错误

我们人为的规定,进程退出码为0时表示进程运行错误.那么进程退出码是其他时该如何确认是什么原因呢?

C中封装了一个strerr的函数.来解决这个问题.

image-20231113144754465

传入参数为对应的错误退出码,返回值为系统中对这段退出码的描述.

我们来看看系统中的错误码描述有几种.

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

image-20231113145131872

image-20231113145149023

总共有134个(0-133).其中,0号退出码表示进程正确执行完毕.

当一个进程结果错误的时候.进程往往会保存他的错误码,在errorno中.这是一个全局变量,同样也仅能存储最近一次错误是什么原因.

image-20231113145640850

例如:

int main()
{
   char *p=(char*) malloc(10000000000*1000*1000*1000*4);
   if(p==NULL)
   {
       printf("errno:%d,because : %s",errno,strerror(errno));
       return errno;
   }
   else
   {
       return 0;
   }
}


我们用malloc向内存申请一个空间.若p==NULL则说明申请失败了.我们就可以通过errno配合strerror读出其的错误信息.

image-20231113150037295

2. 进程异常

进程异常的本质是进程收到了对应的信号而停止了进程.

大多时候,进程异常时代码是没有运行完成的.所以我们并不需要去关注他的退出码是什么.而是关注他的退出信号.

我们写一个一眼错的程序看看什么叫进程异常.

int main()
{
    int a=10;
    a/=0;
    int *p=NULL;
    *p=10;
    return 0;
}

第一个是/0错误,第二个是段错误(访问了不属于自己的内存). 运行看看结果

image-20231113150651796

image-20231113150716070

我们打开之前的kill信号表

kill -l

image-20231113150801025

这两个错误对应的信号是8号与11号.我们来看看是不是

先运行一个简单的监控程序

int main()
{
    while(1)
    {
        printf("ing\n");
        sleep(1);
    }
    return 0;
}

image-20231113151345247

image-20231113151422111

和我们的预期是一样的

3. return()、exit()与_exit()

我们先来看看return与exit的关系

return 为退出当前的函数.

exit 为退出当前的进程.

也就是说如果在main函数中使用,这二者差别不大. 也就是return 0 与 exit(0)等价

如果在其他函数中使用,return 会返回到上一层函数中去,而exit会直接退出这个进程.

那么exit()与_exit()呢?

image-20231113151833793

image-20231113151855912

exit为C封装的库函数,而_exit为系统调用

我们观察一下这个程序

int main()
{
    printf("hello");
    exit(0);
}

会发生什么呢?

image-20231113152133752

那么,换成系统调用会发生什么呢?

int main()
{
    printf("hello");
    _exit(0);
}

image-20231113152210876

printf并不生效了,这是为什么呢?

因为效率原因,printf打印并不会直接输出,而是直接放入到对应的缓冲区当中

而exit会先清除缓冲区,调用析构等语言层面的事情做完.再去调用_exit完成系统内核层面的结束.

而_exit直接完成系统层面的结束了.

我们也可以得出一个结论该缓冲区肯定不在内核中.因为这样exit与_exit的差别就不大了.也就不会出现上面的情况

68)]

printf并不生效了,这是为什么呢?

因为效率原因,printf打印并不会直接输出,而是直接放入到对应的缓冲区当中

而exit会先清除缓冲区,调用析构等语言层面的事情做完.再去调用_exit完成系统内核层面的结束.

而_exit直接完成系统层面的结束了.

我们也可以得出一个结论该缓冲区肯定不在内核中.因为这样exit与_exit的差别就不大了.也就不会出现上面的情况

c3426e8eb17e523c7c052be63453ea3
image-20230905164632777

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 18
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ppeua

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值