Linux--进程终止与等待--0914--0919

目录

1. 引入进程终止

1.2 进程终止的常见方式

2. 如何终止进程

2.1 main

2.1.1 查看退出码

2.2 exit

3. 进程等待

3.1 引入

3.2 进程等待的方法

3.2.1 wait

3.2.2 waitpid

3.2.3 waitpid 测试代码实现1

3.2.4waitpid 测试代码实现2

3.3 进程等待的过程

3.3.1 阻塞等待

3.3.2 非阻塞等待

3.3.3 HANG

模拟父进程调用wait的过程


1. 引入进程终止

当进程终止时,操作系统做了什么?释放进程申请的相关内核数据结构和对应的数据和代码.本质就是释放系统资源.

1.2 进程终止的常见方式

  1. 代码跑完,结果正确.
  2. 代码跑完,结果不正确.
  3. 代码没有跑完,程序崩溃.

2. 如何终止进程

2.1 main

main函数的返回值是给上一级进程的,用来判断执行结果用的.return 0 这里的0其实一种退出码.

0代表运行的结果正确.非零值代表运行的结果不正确.不同的退出码对应着不同的错误原因.

2.1.1 查看退出码

#include <stdio.h>
#include <unistd.h>
#include <string.h>

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

linux下使用 echo $? 以获取最近一个进程,执行完毕的退出码

2.2 exit

需要包含头文件 #include <stdlib.h>

exit在代码的任何地方被调用,都表示直接终止进程.exit是库函数,_exit是系统接口.

调用exit时会调用_exit在内的一系列函数.会执行用户定义的清理函数,冲刷缓冲,关闭流等.

_exit调用时直接终止程序

3. 进程等待

3.1 引入

当子进程退出,父进程不管子进程,子进程就要出于僵尸模式,导致内存泄漏.

父进程创建子进程是用来执行操作的,父进程如何知道执行情况?

3.2 进程等待的方法

等待可以理解成父进程等待子进程进入僵尸状态,一旦子进程进入Z状态,父进程自动回收资源.

如果子进程先执行完毕,只要当父进程执行wait/waitpid函数就可以回收子进程.

3.2.1 wait

#include<sys/types.h>
#include<sys/wait.h>

int status=0;
pid_t ret= wait(&status);
pit_t ret=wait(NULL);
//这里的参数是输出型参数,需要先创建
//用来让上一级获取子进程的退出状态,不关心可用NULL

3.2.2 waitpid

pid_ t waitpid(pid_t pid, int *status, int options);

给的pid>0 该值为需等待的程序的pid, pid=-1 表示等待任意一个子进程,与wait等效.

status 是输出型参数,需要先定义. 当status设置为NULL时 waitpid(pid,NULL,0)等价于wait(NULL)

options 默认为0,表示阻塞等待.


其中status是按照比特位的方式,将32位比特位进行划分使用的。次低八位表示子进程退出的退出码(15~8位),最低七位表示进程接受到的信号。

3.2.3 waitpid 测试代码实现1

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>

int main()
{
    pid_t id = fork();
    if(id < 0)
    {
        perror("fork");
        exit(1); //标识进程运行完毕,结果不正确
    }
    else if(id == 0)
    {
        //子进程
        int cnt = 5;
        while(cnt)
        {
            printf("cnt: %d, 我是子进程, pid: %d, ppid : %d\n", cnt, getpid(), getppid());
            sleep(1);
            cnt--;
        }
        exit(15);
    }
    else
    {
        //父进程
        printf("我是父进程, pid: %d, ppid: %d\n", getpid(), getppid());
        int status = 0; 
        pid_t ret = waitpid(id, &status, 0); //阻塞式的等待!
        if(ret > 0)
        {
            // 0x7F -> 0000.000 111 1111
            printf("等待子进程成功, ret: %d, 子进程收到的信号编号: %d,子进程退出码: %d\n",\
                    ret, status & 0x7F ,(status >> 8)&0xFF); 
            //0x7f --> 0000..0000 0111 1111
            //0xff --> 0000...000 1111 1111
        }
        
    }
}

进程异常退出,或者崩溃(野指针、越界等),本质是操作系统杀掉了进程(kill命令等),通过发送信号的方式。

 

 信号如果不是零,证明不正常跑完,退出码无意义。

退出码也是子进程的数据,当进程进入僵尸状态时,会至少保留该进程的PCB信息。task_struct里面保留了任何进程退出时的结果信息。wait/waitpid本质是读取了子进程的task_struct结构体。

而wait和waitpid是系统调用,系统有权限去访问内核数据结构对象(task_struct)。

3.2.4waitpid 测试代码实现2

父进程视角获得子进程的有退出结果信息可以用相关宏实现。

int main()
{    //..
    //..
    //父进程
    int status=0;
    pid_t result=waitpid(id,&status,0);//等待成功返回子进程pid
    if(result>0)
    {
        if(WIFEXITED(status))
        {
            printf("子进程执行完毕,子进程的退出码是:%d\n",WEXITSTATUS(status));
        }
        else
        {
            printf("子进程异常退出:%d\n ",WIFEXITED(status));
        }
    }
}

3.3 进程等待的过程

3.3.1 阻塞等待

options=0时为阻塞等待。意思是只有子进程退出的时候,父进程才能够调用waitpid函数。阻塞等待的好处是可以让进程退出具有一定的顺序,可在父进程中进行更多的收尾工作。

3.3.2 非阻塞等待

options=WNOHANG时为非阻塞等待。意思是子进程还未退出时,父进程可以等一等,先处理其他事情。

3.3.3 HANG

#define WNOHANG 1

HANG一般是指运行停止的状态,即没有被CPU调度。HANG状态要么是在阻塞状态,要么就是等待被调度。WNOHANG 意思为wait调用时不进入阻塞状态。

模拟父进程调用wait的过程

waitpid(child_pid, &status, options)

{        if(status中的信息是 已退出)

        {

                返回子进程的pid

        }

        else if(status中的信息是没退出)

        {

                if(options==0)

                挂起父进程 //将父进程pcb结构体放入等待队列 进入阻塞状态

                //后面的代码不执行了,当条件满足的时候,父进程在之前运行到的位置被唤醒

                else if(options==WNOHANG)

                //这里可以继续执行代码 不阻塞进程

                return 0;//正常退出 waitpid这个系统调用立马返回。

                        //但会持续调用 直到操作系统允许访问(子进程退出)  

        }

        else //出错了

        return -1;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值