Linux:进程等待wait函数&阻塞&coredump

进程只要是收到什么信号,则表明这个进程是异常退出的

简述

进程等待的作用:

  • 父进程在它的执行代码中调用进程等待的方法,等待子进程退出,防止子进程变成僵尸进程
  • 实质:
    子进程保存了自己的进程退出码给父进程,父进程获取了退出码后才能释放子进程资源

wait函数(是一个阻塞接口)

pid_t wait (int* status)

  • 作用:等待当前调用者的任意一个子进程退出,获取返回值释放资源
    多个子进程退出只能处理一个
  • 函数参数是输出型参数,通过形参修改实参
    将wait函数内部计算的某个结果通过status变量返回给调用者
  • 返回值
    成功:返回处理的退出的子进程的pid
    失败:返回-1
  • 阻塞:为了完成一个功能发起了一个调用,但是这个调用完成条件不具备,则接口一直等待不返回
  • 非阻塞接口:为了完成一个功能发起了一个调用,但是这个调用完成条件不具备,则立即报错返回

参数status

status是一个指针类型占四个字节,但是实际中只使用到后16位

  • 退出码 + coredump标志位 + 退出信号
  • 高8位表示退出码;
  • 1位的coredump标志位
    翻译过来是核心转储,程序异常退出,保存程序运行程序,一般是关闭的
  • 低7位的退出信号
    在这里插入图片描述

退出码:程序正常退出时用到

  • main函数的return返回时,return后的数字就是退出码
  • exit和_exit中的参数就是退出码

coredump标志位,退出信号是程序异常退出时用到:

  • 为0表示该进程在退出时没有内存镜像文件的产生(也就是说没有coredump产生)
  • 为1则有镜像文件产生,当前程序退出异常

退出信号进程异常退出时收到的几号信号

coredump(先学信号再学这个)

产生coredump文件不能判断进程是否正常退出的原因:

  • 程序在运行时崩溃(例如解引用空指针),该进程会收到崩溃信号;
  • 该信号可能会让进程产生一个coredump文件,这个文件并不是收到崩溃信号就一定会产生。
  • 是否产生coredump文件取决于:
    磁盘硬限制,空间大小不足;
    系统的软限制,进程可以产生coredump文件但是系统不让其产生
  • 一个进程在异常退出时,如果收到了某些信号,系统为了方便用户调试在进程退出时触发coredump机制
    这个机制叫核心转储
  • 外部问题和代码没关系,而3468 11信号是程序内部的问题导致进程出现终止
  • 对应的标志位会被置1,并且会在当前路径下生成一个core.xxxx文件(xxxx是对应的进程号)
  • 核心转储的本质coredump会把进程在运行中各种数据和代码信息转储到磁盘上方便调试
    直接gdb后打印 core-file core.xxx就定位到错误发生的行数了

异常退出是因为收到了特定的信号,通过status右移7位得到
发信号的过程在信号部分讲解

wait阻止子进程变成僵尸进程

在这里插入图片描述

  • 父进程一旦调用wait函数后,当子进程没有退出前,wait函数是不会返回;
  • 父进程调用wait函数,wait函数就压到父进程的栈帧上,子进程没有退出,父进程栈帧是不会销毁的,也就是说wait函数不会出栈返回

退出码&退出信号的获取与优先级

  • 程序正常退出的时候,也就是经过return或者exit退出,都是设置了退出码
  • 但是如果程序是运行途中,异常崩溃的,则保存的退出码根本就没有意义,因为根本就没有进行设置
  • 异常信号值,作用就是保存异常退出的原因,为0表示程序正常退出,!0则表示异常退出
  • 所以先取信号低七位值是否是0,是0表示正常退出,再取高八位的退出码

1.判断是否有退出信号

  • 正常退出时,退出信号7位全=0;异常退出,退出信号>0;
  • 所以
    int _status=wait(&status);
    status & 0xfff ffff;,等于0正常退出,>0异常退出

2.判断coredump标志位

  • (ststus >> 7) & 0x1;

3.判断退出码

  • (ststus >> 8) & 0xff;也就是按位与上八个一
  • 或者两个宏

4.退出信号

  • ststus & 0x7f

阻塞:

把进程从运行队列中拿出来放到等待队列中,在等待一个条件
这是在等待软件

阻塞概念:当调用结果返回之前,当前的执行流会被挂起,并在得到结果之后返回

  • 或者说:调用结果返回前,当前线程会被挂起,并在得到结果之后返回
  • 例如:父进程被wait函数阻塞,父进程就会被挂起,必须等到子进程结束后才能返回
  • 使用上述代码,只需给父进程处加一个死循环即可;
  • 运行后通过pstack+父进程进程号查看父进程栈帧;

在这里插入图片描述
在这里插入图片描述
父进程一直在wait,并没有返回;

对阻塞和非阻塞理解:
1.子进程一种在运行;

  • 阻塞:父进程等待子进程运行完后退出;这就是阻塞
  • 非阻塞:父进程不等子进程运行是否运行完毕就退出,这样可能会导致孤儿进程;这就是非阻塞

2.子进程已退出

  • 阻塞:父进程正常退出
  • 非阻塞:父进程正常退出

对于两种非阻塞的情况,父进程都是直接退出,但是两种情况父进程退出后,一种正常一种不正常

waitpid函数

返回值:
等待成功,返回子进程退出码
非阻塞等待,没有等到子进程则返回0,等待失败-1,成功返回子进程退出码

wait函数的实现是调用waitpid函数实现
在这里插入图片描述

  • 非阻塞模式下waitpid函数返回是没有等待子进程的;
  • waitpid函数在非阻塞模式下只调用一次并且也没等待到子进程退出,再不去调用该函数;
  • 等到子进程退出后子进程就会变成僵尸进程;
  • 所以在非阻塞模式下需要搭配循环;

使用非阻塞,父进程可以在等待的同时做别的事情
在这里插入图片描述在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值