Linux - 进程控制(进程等待)

进程等待必要性

之前讲过,子进程退出,父进程如果不管不顾,就可能造成‘僵尸进程’的问题,进而造成内存泄漏。
另外,进程一旦变成僵尸状态,那就刀枪不入,“杀人不眨眼”的kill -9 也无能为力,因为谁也没有办法杀死一个已经死去的进程。最后,父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出。父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息

进程等待的方法

通过man手册进程查看

man 2 wait

wait()函数

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int*status);
返回值:
 成功返回被等待进程pid,失败返回-1。
参数:
 输出型参数,获取子进程退出状态,不关心则可以设置成为NULL

下面测试一下wait()函数

接下来观察下进程状态,首先运行

 while :; do ps axj | head -1 && ps ajx | grep mytest | grep -v grep; sleep 1; echo "----------------"; done

接下来执行程序

执行程序的同时查看进程状态

这样观察不到现象,代码改进一下

waitpid()函数

pid_ t waitpid(pid_t pid, int *status, int options);
返回值:
    当正常返回的时候waitpid返回收集到的子进程的进程ID;
    如果设置了选项WNOHANG,而调用中waitpid发现没有已退出的子进程可收集,则返回0;
    如果调用中出错,则返回-1,这时errno会被设置成相应的值以指示错误所在;
参数:
   pid:
     Pid=-1,等待任一个子进程。与wait等效。
     Pid>0.等待其进程ID与pid相等的子进程。
   status:
     WIFEXITED(status): 若为正常终止子进程返回的状态,则为真。(查看进程是否是正常退出)
     WEXITSTATUS(status): 若WIFEXITED非零,提取子进程退出码。(查看进程的退出码)
   options:
      WNOHANG: 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。
1.如果子进程已经退出,调用wait/waitpid时,wait/waitpid会立即返回,并且释放资源,获得子进程退出信息。
2.如果在任意时刻调用wait/waitpid,子进程存在且正常运行,则进程可能阻塞。
3.如果不存在该子进程,则立即出错返回。

获取子进程status

wait和waitpid,都有一个status参数,该参数是一个输出型参数,由操作系统填充。
如果传递NULL,表示不关心子进程的退出状态信息。否则,操作系统会根据该参数,将子进程的退出信息反馈给父进程。
status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):

下面是获取退出码

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main()
{
    pid_t id = fork();
    if (id == 0)
    {
        int cnt = 5;
        while (cnt)
        {
            printf("我是子进程,我还活着呢,我还有%dS,pid:%d,ppid:%d\n", cnt--, getpid(), getppid());
            sleep(1);
        }
        exit(107);
    }
    // 父进程
    int status = 0;
    pid_t ret_id = waitpid(id, &status, 0);
    printf("我是父进程,等待子进程成功,pid:%d,ppid:%d,ret_id:%d,child exit code:%d\n", getpid(), getppid(), ret_id, (status >> 8) & 0xFF);
    return 0;
}

其中status>>8&0xff获得整型值

下面是获取异常信号码

获取异常信号status&0x7f得出整型值

退出码为0,我们制造一个异常,在查看异常信号

我们继续改下程序,使程序无限循环

死循环也可以杀掉进程。

父进程在等待子进程的时候,也可以做别的事情

具体代码实现

进程的阻塞等待方式

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


int main()
{
    pid_t pid;
    pid = fork();
    if (pid < 0)
    {
        printf("%s fork error\n", __FUNCTION__);
        return 1;
    }
    else if (pid == 0)
    { // child
        printf("child is run, pid is : %d\n", getpid());
        sleep(5);
        exit(257);
    }
    else
    {
        int status = 0;
        pid_t ret = waitpid(-1, &status, 0); // 阻塞式等待,等待5S
        printf("this is test for wait\n");
        if (WIFEXITED(status) && ret == pid)
        {
            printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));
        }
        else
        {
            printf("wait child failed, return.\n");
            return 1;
        }
    }
    return 0;
}

进程的非阻塞等待方式

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

int main()
{
    pid_t pid;

    pid = fork();
    if (pid < 0)
    {
        printf("%s fork error\n", __FUNCTION__);
        return 1;
    }
    else if (pid == 0)
    { // child
        printf("child is run, pid is : %d\n", getpid());
        sleep(5);
        exit(1);
    }
    else
    {
        int status = 0;
        pid_t ret = 0;
        do
        {
            ret = waitpid(-1, &status, WNOHANG); // 非阻塞式等待
            if (ret == 0)
            {
                printf("child is running\n");
            }
            sleep(1);
        } while (ret == 0);

        if (WIFEXITED(status) && ret == pid)
        {
            printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));
        }
        else
        {
            printf("wait child failed, return.\n");
            return 1;
        }
    }
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/1704.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于java下Springboot框架实现旅游管理平台系统

基于java下Springboot框架实现旅游管理平台系统开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

自动驾驶自主避障概况

文章目录前言1. 自主避障在自动驾驶系统架构中的位置2. 自主避障算法分类2.1 人工势场法&#xff08;APF&#xff09;2.1.1引力势场的构建2.1.2斥力势场的构建2.1.3人工势场法的改进2.2 TEB&#xff08;Timed-Eastic-Band, 定时弹性带&#xff09;2.3 栅格法2.4 向量场直方图(V…

基于鲸鱼算法的极限学习机(ELM)分类算法-附代码

基于鲸鱼算法的极限学习机(ELM)分类算法 文章目录基于鲸鱼算法的极限学习机(ELM)分类算法1.极限学习机原理概述2.ELM学习算法3.分类问题4.基于鲸鱼算法优化的ELM5.测试结果6.参考文献7.Matlab代码摘要&#xff1a;本文利用鲸鱼算法对极限学习机进行优化&#xff0c;并用于分类问…

C++继承

文章目录继承的概念和定义继承的概念继承定义继承定义格式继承基类成员访问方式的变化基类和派生类对象赋值转换继承中的作用域派生类的默认成员函数继承与友元继承与静态成员复杂的菱形继承及菱形虚拟继承菱形虚拟继承菱形虚拟继承原理菱形虚拟继承中虚指针应用继承的总结和反…

【C语言】字符串函数和内存函数

前言&#x1f338;在我们编写C程序时&#xff0c;除了使用自定义函数&#xff0c;往往还会使用一些库函数&#xff0c;例如标准输入输出函数printf&#xff0c;scanf&#xff0c;字符串函数strlen&#xff0c;内存函数memset等等&#xff0c;使用这些系统自带的库函数可以轻松地…

MongoDB【部署 01】mongodb最新版本6.0.5安装部署配置使用及mongodb-shell1.8.0安装使用(云盘分享安装文件)

云盘分享文件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/11sbj1QgogYHPM4udwoB1rA 提取码&#xff1a;l2wz 1.mongodb简单介绍 MongoDB的 官网 内容还是挺丰富的。 是由 C语言编写的&#xff0c;是一个基于分布式文件存储的开源数据库系统。在高负载的情况下&…

【JavaEE初阶】第八节.网络原理网络层和数据链路层,应用层

文章目录 前言 一、网络层协议 1.1 IP协议 1.2 IP地址&#xff1b; 1.3 路由选择&#xff1b; 二、数据链路层 2.1 以太网协议&#xff1b; 三、应用层&#xff1b; 3.1 应用层协议DNS&#xff1b; 3.2 DNS是如何完成转换的&#xff1b; 3.3 如何解决DNS访问量太高的…

c语言的基础知识之结构体

目录前言结构体结构的自引用typedef函数结构体内存对齐修改默认对齐数位段什么是位段位段的内存分配位段的跨平台问题位段的意义以及应用枚举枚举常量的赋值枚举的优点总结前言 欢迎来到戴佳伟的小课堂&#xff0c;那今天我们讲啥呢&#xff1f; 问得好&#xff0c;我们今天要讲…

数据库面试题——锁

了解数据库的锁吗&#xff1f; 锁是数据库系统区别于文件系统的一个关键特性&#xff0c;锁机制用于管理对共享资源的并发访问。 InnoDB下两种标准行级锁&#xff1a; 共享锁&#xff08;S Lock&#xff09;&#xff0c;允许事务读一行数据。 排他锁&#xff08;X Lock&…

图解如何一步步连接远程服务器——基于VScode

基于VScode连接远程服务器 安装Remote-SSH等插件 想要在vscode上连接远程服务器需要下载Remote-SSH系列插件&#xff1a; 直接在插件中搜索remote&#xff0c;即可找到&#xff0c;选择图片中的3个插件&#xff0c;点击install安装。 配置Remote-SSH 在这个步骤有多种操作…

和ChatGPT对比,文心一言的表现已经是中国之光了

网络上各种测评满天飞&#xff0c;这里就不展开说了&#xff0c;针对“chatgpt”这项技术的难点&#xff0c;是十分巨大的。当你对文心一言以及其他国产AI软件存在不满的时候&#xff0c;你可以简单对着chatgpt或者文心一言搜索&#xff01;ChatGPT技术难点通俗来讲难度&#x…

节流还在用JS吗?CSS也可以实现哦

函数节流是一个我们在项目开发中常用的优化手段&#xff0c;可以有效避免函数过于频繁的执行。一般函数节流用在scroll页面滚动&#xff0c;鼠标移动等。 为什么需要节流呢&#xff0c;因为触发一次事件就会执行一次事件&#xff0c;这样就形成了大量操作dom,会出现卡顿的情况…

LeetCode:35. 搜索插入位置

&#x1f34e;道阻且长&#xff0c;行则将至。&#x1f353; &#x1f33b;算法&#xff0c;不如说它是一种思考方式&#x1f340;算法专栏&#xff1a; &#x1f449;&#x1f3fb;123 一、&#x1f331;35. 搜索插入位置 题目描述&#xff1a;给定一个排序数组和一个目标值&…

CentOS8服务篇10:FTP服务器配置与管理

一、安装与启动FTP服务器 1、安装VSFTP服务器所需要的安装包 #yum -y install vsftpd 2、查看配置文件参数 Vim /etc/vsftpd/vsftpd.conf &#xff08;1&#xff09;是否允许匿名登录 anonymous_enableYES 该行用于控制是否允许匿名用户登录。 &#xff08;2&…

年报前瞻:文化产业高质量发展确定性,关注腾讯音乐三大关键能力

港股进入年报季&#xff0c;今年的披露期拥有比往年更多的看点。 一方面&#xff0c;经济复苏态势明显&#xff0c;线上线下消费均有回暖&#xff0c;市场已经对去年的整体表现有更多预期&#xff0c;正关注企业对后续发展的思考&#xff1b;另一方面&#xff0c;两会结束&…

2023美赛C题【分析思路+代码】

以下内容为我个人的想法与实现&#xff0c;不代表任何其他人。 文章目录问题一数据预处理时间序列模型创建预测区间单词的任何属性是否影响报告的百分比&#xff1f;如果是&#xff0c;如何影响&#xff1f;如果不是&#xff0c;为什么不是&#xff1f;问题二问题三难度评估模型…

【Vue3】利用vite创建vue3项目

&#x1f3c6;今日学习目标&#xff1a;利用vite创建vue3项目 &#x1f603;创作者&#xff1a;颜颜yan_ ✨个人格言&#xff1a;生如芥子&#xff0c;心藏须弥 ⏰本期期数&#xff1a;第二期 &#x1f389;专栏系列&#xff1a;Vue3 文章目录前言vite简介利用vite创建vue3项目…

二叉搜索树

1.基础概念介绍 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 1.若它的左子树不为空&#xff0c;则左子树上所有节点的值都小于根节点的值 2.若它的右子树不为空&#xff0c;则右子树上所有节点的值都大于根节点的值 3.它…

设置Typora图床(Github)

PicGo&#xff0c;Github&#xff0c;Typora Nodejs下载&#xff1a; Node.js PicGo下载&#xff1a; GitHub - Molunerfinn/PicGo: A simple & beautiful tool for pictures uploading built by vue-cli-electron-builder 选择downloads或release. 然后进行安装。 Gith…

经典PID控制算法原理以及优化思路

文章目录0、概念1、理解2、实现3、优化4、引用0、概念 PID算法是工业应用中最广泛算法之一&#xff0c;在闭环系统的控制中&#xff0c;可自动对控制系统进行准确且迅速的校正。PID控制&#xff0c;即Proportional – Integral(I) – Derivative(D) Control, 实际上是三种反馈…
最新文章