文章目录

  • 项目场景:
  • 问题描述以及分析过程:
  • defunct(僵尸进程):
  • QProcess的实现:
  • 理论原因:
  • 尝试修改一:
  • 第一次痛定思痛:
  • 尝试修改二:
  • 第二次修改能满足要求:
  • 使用startdetched分离进程:

项目场景:

  • 2022-04-28

    涉及Linux下的多进程编程,比较让人绕晕。
    初步以为,是由于在子进程中,又创建了子进程,导致的最后创建的子进程异常。

  • 2022-04-29

    今天早早的到了单位,任然放不下昨天的问题,于是乎一坐下,我就翻起了经典《UNIX高级环境编程》。
    一小时之后,似乎有点眉目,便更新了此文档。


问题描述以及分析过程:

  • 2022-04-28
  1. 使用fork函数,创建子进程A;
  2. A主要 调用execvp函数拉起QT主程序B;
  3. 主程序B中调用QProcess::start函数调用进程C(ffmpeg的命令);
  4. B中connect进程C的finished信号,或者waitforfinished均失败;
异常有:1. finished信号不触发;2. ffmpeg转码明明结束了,进程却不推出;3. 调用waiforfinished一直阻塞,直到30秒超时;
  • 2022-04-29

看过书后,再分析这个问题,似乎有底气了。 介绍一下我的主题部分:
broadcast_daemon: 守护进程,负责fork子进程并且监听子进程状态
broadcast_media_ser: 主服务程序
ffmpeg: 负责转码的进程

  1. 查看一下这个子进程的ID,使用指令分析:“ps -ef|grep ffmpeg”,结果如下:
  2. 可以看到,该子进程的pid=2992,它的父进程ppid=2983;查看2983进程,正式我守护进程拉起的QT主程序;
  3. 然看到ffmpeg的进程此时已是“defunct”进程,即“僵尸进程”了;
  4. 按惯例贴出我的代码:

    5.考虑僵尸进程到底出现的原因

defunct(僵尸进程):

摘自网络结合个人总结:

  1. 什么是僵尸进程?

僵尸进程是一个早已死亡的进程,但在进程表(processs table)中仍占了一个位置(slot)。

  1. 僵尸进程产生的原因是什么?(归其原因:需要wait\waitpid)

在 Linux 系统中,一个子进程结束了,但是他的父进程没有等待(调用wait / waitpid)他,那么他将变成一个僵尸进程;
如果该进程的父进程已经先结束了,那么该进程就不会变成僵尸进程;
每个进程结束的时候,系统都会扫描当前系统中所运行的所有进程,看看有没有哪个 进程是刚刚结束的这个进程的子进程,如果是的话,就由Init进程来接管他,成为他的父进程,从而保证每个进程都会有一个父进程。
而Init进程会自动 wait其子进程,因此被Init接管的所有进程都不会变成僵尸进程。

  1. 僵尸进程的危害?

进程号会一直被占用,但是系统的进程表容量是有限的,所能使用的进程号也是有限的,如果大量的产生僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。
所以,defunct进程不仅占用系统的内存资源,影响系统的性能,而且如果其数目太多,还会导致系统瘫痪。而且,由于调度程序无法选中Defunct


QProcess的实现:

主要关注其创建的原来、以及waitforfinished函数、finished信号等产生的原理:
QT的通信可分为QT内部通信和外部通信两大类;

  1. QProcess进程的三个接口实现:

QProcess::execute():
此函数是以阻塞的方式打开外部程序,只有外部程序执行完成后,主程序才会继续执行。外部程序的标准输出、标准错误都是重定向到主程序的标准输出和标准错误的。
QProcess::start(): 此函数是以子进程的 方式打开外部程序的,外部进程与主程序互不干扰,但外部进程的父进程就是主程序。
QProcess::startDetached():
此函数是以分离的方式打开外部程序的,外部程序与主程序互不干扰,外部进程的父进程是系统的init进程。

  1. QProcess的机制分析:

启动QProcess的主程序为父进程,QProcess的调用为子进程;他们之间的通信机制如同常用的父子通信机制。而最主要的QProcess实现父子进程间的通信过程是运用Linux系统的无名管道来实现的,所以它会有I/O设备的write、read函数等操作。

理论原因:

综合上面的分析,现在得出以下结论:

  1. 使用QProcess的start函数之后,QT主程序作为父进程,没有调用wait,导致子进程变成了僵尸进程;

尝试修改一:

  1. 发现一个问题:代码查看我的上一篇:
    链接在此:分享一份Linux守护进程代码
  2. 我发现以下问题:

1.在圈出来的函数中,启动的程序,它是可以处理QProcess的信号的,并且我们的ffmpeg也不会变成僵尸进程;
2. 在initWatchDog看门狗程序中,启动的进程则无法处理,这就很奇怪;
3. 于是乎开始分析守护进程的代码异常;

  1. 第一次启动时,waitdog正在挂起pause;此时一切是正常的。

  2. 当我尝试kill掉子进程broad_media_ser时,情况如下:

先是接收到了17;(Child status has changed),发现信号是9,这个时候就开始调用fork,当pid==0表示子进程空间,

执行下面代码;

  1. 通常来说,pid==0表示子进程空间,pid!=0表示父进程空间;真相大白了,父进程空间中并没有wait其结束;修改成如下代码:

  2. 当重新试一下之后:失败了!!!

发现问题依旧!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!纳尼???????

第一次痛定思痛:

  1. 我发现在守护进程以及QT主服务之间,各个流程都是OK的,没有问题;
  2. 我发现,问题的集中点在于QT主服务已经是子进程,它作为父进程再创建子进程ffmpeg,ffmpeg究竟应该被谁wait???

尝试修改二:

  1. 我用以下的代码测试了一下,发现是OK的
  2. 说明,QT主程序作为子进程,被频繁创建肯定没有问题;QPRocess类也是可以被支持的。
  3. 最后我把守护进程的代码改成了下面这样,用最简单的方式实现了功能:
int main()
{int pid = 0;int status = 0;param = new char[100];memset(param,0,100);pcmd = new char[1024];memset(pcmd,0,1024);strcpy(param,"-log");get_process_path(pcmd);strcat(pcmd,pservername);while(true){pid = fork();if(pid == 0){childProcessFunc();}if(pid != 0){wait(&status);if (WIFSIGNALED(status)){int signalNum = WTERMSIG(status);printf("Child process was killed by signal num: %d\n", signalNum);}// 检测是否生成了core文件if (WCOREDUMP(status)){printf("Child process core dump file generated\n");}// 等待3秒钟重新启动子进程sleep(3);}}delete[] pcmd;delete[] param;return 0;
}

第二次修改能满足要求:

原因应该还是代码运用错误。

使用startdetched分离进程:

分离后,可以通过读取进程表,来进行判断,这也是一种方法。

Linux下QProcess不产生finished信号、waitforfinished阻塞超时【defunct进程】相关推荐

  1. linux c语言 信号,linux下基于C语言的信号编程实例

    搜索热词 本文实例讲述了linux下基于C语言的信号编程方法.分享给大家供大家参考.具体如下: #include #include #include #include #include void si ...

  2. linux 下取进程占用 cpu/内存 最高的前10个进程

    1. linux 下 取进程占用 cpu 最高的前10个进程 ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head ps auxw|head -1 ...

  3. 在windows和linux下如何查看80端口占用情况?是被哪个进程占用?如何终止等

    一.在windows下如何查看80端口占用情况?是被哪个进程占用?如何终止等 这里主要是用到windows下的DOS工具,点击"开始"--"运行",输入&quo ...

  4. Linux下通过mail发送qq邮件出现连接超时的情况

    Linux下通过mail发送qq邮件出现连接超时的情况 一.一般来说都是smtp的地址配置错误: 之前配置过的地址有: 1) set smtp=smtp.qq.com 2) set smtp=smtp ...

  5. Linux下C语言开发(信号signal处理机制)

    信号signal处理是Linux程序的一个特色,用信号处理来模拟操作系统的中断功能,对于系统程序员来说是最好的一个选择了.同样信号处理也是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概 ...

  6. linux设置进程不忽略信号,Linux下后台进程编写中屏蔽信号

    signal(SIGINT, SIG_IGN);      //当在终端上按下ctrl+c后,会产生SIGINT信号. signal(SIGHUP, SIG_IGN);    //终端退出时,会给所有 ...

  7. Linux下的C编程实战(开发平台搭建,文件系统编程,进程控制与进程通信编程,“线程”控制与“线程”通信编程,驱动程序设计,专家问答)

    Linux下的C编程实战(一) ――开发平台搭建 1.引言 Linux操作系统在服务器领域的应用和普及已经有较长的历史,这源于它的开源特点以及其超越Windows的安全性和稳定性.而近年来,Linux ...

  8. Linux下怎么使用任务管理器和真人接口源码出售进程管理

    大家都知道在Windows下怎么使用任务管理器来管理进程,真人接口源码出售[企鹅21717-93408]那么在linux下呢? 今天简单介绍一下怎么在linux使用任务管理器管理进程,让我们的linu ...

  9. linux 进程内存排行,linux下获取占用CPU/内存资源最多的10个进程[转自亿唐网]

    inux下获取占用CPU资源最多的10个进程,可以使用如下命令组合: ps aux|head -1;ps aux|grep -v PID|sort -rn -k +3|head linux下获取占用内 ...

最新文章

  1. el table怎么获取最后一行_elementUi表格插入额外一行怎么操作
  2. CodeForces - 932G Palindrome Partition(回文自动机+Palindrome Series优化dp)
  3. Oracle修改字段类型方法
  4. 详解最短路算法模板(dijkstra+floyd+spfa)
  5. jquery对文本赋值和取值_jQuery对表单元素的取值和赋值操作代码
  6. WDS系列之四:自定义安装映像
  7. mysql metadata lock(二)
  8. 详解BetterZip对压缩包注释的一些相关小功能
  9. 如何使用:after伪元素和:before伪元素
  10. iapp导入源码使用教程,iapp保存图像代码教程
  11. 平板波导 matlab,非对称平板波导色散曲线求解(附matlab程序).doc
  12. 希尔伯特空间等各空间介绍-数据升维以及核函数选择
  13. 串口转usb驱动c语言程序,usb serial驱动下载-usb serial converter驱动下载 官方版usb转串口驱动程序-win7/8/10/xp32/64位-IT猫扑网...
  14. Redis常用命令大集合(快速入门)
  15. 网络虚拟化中的 offload 技术:LSO/LRO、GSO/GRO、TSO/UFO、VXLAN
  16. 【联盛德W806上手笔记】十、ADC
  17. Cocos2d-X Box2D内容讲解
  18. ImportError:attempted relative import with no known parent package
  19. 模拟重力场(多方向运动+碰撞检测+重力加速度+能量损失)
  20. 云原生和云计算的区别,普通人都能看懂!

热门文章

  1. python中的正则表达式re模块_Python中的re模块--正则表达式
  2. 【openMV or openCV】
  3. 安装caffe中间遇到的一些问题
  4. 某注册页面存在手机短信验证码绕过
  5. 【接口技术】实验四:8254定时器与计数器
  6. Error: Canceled future for execute_request message before replies were done
  7. Android旗舰机与苹果,真正的旗舰之王!iPhone和国产安卓旗舰机,谁才能够当之无愧?...
  8. Nginx安装成windows server 2016机器的服务
  9. F. Equalize the Array【学习进度条2】
  10. 联盟新闻 - DALI 联盟发布 DALI+ 技术