【Linux】进程控制

img

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

本篇导航

  • 0. 进程退出退出概念
  • 1. 进程运行完毕
    • 1.1 结果正确
    • 1.2 结果错误
  • 2. 进程异常
  • 3. return()、exit()与_exit()

在这里插入图片描述

0. 进程退出退出概念

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

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

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

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

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

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

#include 
int main()
{
    printf("Hello World\n");
    return 0;
}

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

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

echo $?

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

1. 进程运行完毕

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

1.1 结果正确

例如之前演示的:

#include 
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;
}

【Linux】进程控制_第1张图片

【Linux】进程控制_第2张图片

总共有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

【Linux】进程控制_第3张图片

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

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

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

【Linux】进程控制_第4张图片

【Linux】进程控制_第5张图片

和我们的预期是一样的

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);
}

【Linux】进程控制_第6张图片

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

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

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

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

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

68)]

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

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

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

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

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

【Linux】进程控制_第7张图片
image-20230905164632777

你可能感兴趣的:(Linux,linux,运维,服务器,c++,进程控制)