【进程等待】阻塞等待 | options非阻塞等待

目录

waitpid

阻塞等待

options&非阻塞等待 

pid_t返回值 

阻塞等待VS非阻塞等待


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。

阻塞等待

  • 如果子进程没有退出,而父进程在进行执行waitpid进行等待,阻塞等待。
  • 大部分IO类的函数例如scanf各种各样的接口,只要涉及IO的或多或少会可能出现阻塞的状态。
  • 现在所用的大部分接口都是阻塞接口(逻辑简单,容易实现)
  • **阻塞等待(Blocking Wait)**在编程中通常指的是一个线程或进程在等待某个条件满足或某个操作完成之前,会暂停执行其他任务,处于等待状态。这种状态会一直持续,直到等待的条件满足或操作完成,线程或进程才会继续执行后续的任务。在Java中,阻塞等待常用于多线程编程中,用于线程之间的同步和通信。

进程阻塞:

  • 把进程的R状态设置为S状态
  • 把进程的PCB从运行队列移动到等待队列中,不再被调度,而是等待
  • 本质上是等待某种条件发生。
  1. 软件条件满足(子进程退出)
  2. 硬件资源就绪(scanf键盘输入数据发生) 

options&非阻塞等待√

在子进程运行期间,父进程除了等待子进程或者是休眠,能不能干点其他的事情❓

  • 当然可以,在父进程等待,阻塞状态。可以通过设置options来让父进程干点事情。不阻塞等待而是非阻塞等待。

什么又是非阻塞等待呢❓用代码该怎么去实现呢❓ 

  • **非阻塞等待(Non-blocking Wait)**则与阻塞等待相反。当线程或进程在等待某个条件满足或某个操作完成时,它不会暂停执行其他任务,而是会继续执行后续的任务。也就是说,即使等待的条件还没有满足或操作还没有完成,线程或进程也不会被阻塞,而是会继续执行其他的操作。

  • 通过设置options的宏值WNOHANG(wait no hang 等待没有阻塞 = 非阻塞等待)

  • 在计算机中,"HANG" 通常指的是程序或系统出现无响应或停顿的状态,也就是常说的“卡住”或“死机”。当程序或系统由于某种原因(如资源锁定、死循环、死锁或外部系统交互问题等)而无法继续正常执行时,就可能会出现"HANG"的情况。这种情况下,用户可能无法与程序或系统进行交互,需要等待程序或系统恢复正常或进行重启操作。另外,在一些特定的语境下,"HANG" 也可能被用来描述服务器或数据库的某些服务出现故障或无法访问的情况,这也可以被视为一种"宕机"现象。在这种情况下,"HANG" 指的是服务器或数据库的服务因为某种原因而停止响应或无法提供服务。

具体操作

  • options这个参数只要一设置就会出现非阻塞等待。
  • 设置waitpid的WNOHANG本质上是检测一次进程的状态变化。
  • 调用一次waipid就检测一次。每次调用都是检测,多次调用多次检测。
  • 非阻塞等待调用多次waitpid,调用waitpid检测是否退出等待过程无问题,只是子进程还未终止,需要等待下次等待。
  • 综上:非阻塞等待的时候 + 循环 = 非阻塞轮询
 1: myprocess.c
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4 #include<stdlib.h>
  5 #include<sys/types.h>
  6 #include<sys/wait.h>
  7 
  8 void ChildRun()
  9 {
 10   int cnt = 5;
 11   while(cnt--)
 12   {
 13     printf("I am child,pid: %d,ppid: %d,cnt: %d\n",getpid(),getppid(),cnt);
 14     sleep(1);
 15   }
 16 }
 18 int main()
 19 {
 20   printf("I am father,pid: %d,ppid: %d\n",getpid(),getppid());//父进程
 21   pid_t id = fork();
 22   if(id == 0)//child子进程
 23   {
 24     //子进程循环运行
 25     ChildRun();
 26     printf("Child quit...\n");
 27     exit(1);//终止进程,子进程直接僵尸
 28   }
 29   //father
 30   //父进程,父进程在子进程运行期间5ms干点别的事情....
 31   while(1)
 32   {
 33       int status = 0;                                                                                        
 34       pid_t rid = waitpid(id, &status, WNOHANG);
 35       if(rid == 0)
 36       {
 37         sleep(1);
 38         printf("child is running,father check next time !\n");
 39         //DoOtherThing();
 40       }
 41       else if(rid > 0)
 42       {
 43         if(WIFEXITED(status))
 44         {
 45           printf("child quit normal,child exit code: %d\n",WEXITSTATUS(status));
 46         }
 47         else
 48         {
 49           printf("child quit unnormal!\n");
 50         }
 51         printf("wait success,rid: %d\n",rid);
 52         break;
 53       }
 54       else
 55       {
 56         printf("wait fail !\n");
 57         break;
 58       }                                                                                                      
 59   }
 60  //printf("father quit,status: %d,code: %d,signal: %d\n",status,(status>>8)&0XFF,status&0X7F);
 61 }

解耦☞分析代码逻辑 

【回调函数方式设计一个DoOtherThing在父进程等待的时候实现其他功能】  

【task.c】 

#include "task.h"

void PrintLog()
{
    printf("begin PrintLog...\n");
}
void Download()
{
    printf("begin Download...\n");
}
void MysqlDataSync()
{
    printf("begin MySQLDataSync...\n");
}

【task.h】 

#pragma once

#include <stdio.h>

void PrintLog();
void Download();
void MysqlDataSync();

 【myprocess.c】

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

typedef void(*func_t)();

#define N 3
func_t tasks[N] = {NULL};

void LoadTask()
{
    tasks[0] = PrintLog;
    tasks[1] = Download;
    tasks[2] = MysqlDataSync;
}
void HandlerTask()
{
    for(int i = 0; i < N; i++)
    {
        tasks[i](); // 回调方式
    }
}

// fahter
void DoOtherThing()
{
    HandlerTask();
}


void ChildRun()
{
    //int *p = NULL;
    int cnt = 5;
    while(cnt)
    {
        printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);
        sleep(1);
        cnt--;
        //*p = 100;
    }
}

int main()
{
    printf("I am father, pid: %d, ppid:%d\n", getpid(), getppid());

    pid_t id = fork();
    if(id == 0)
    {
        // child
        ChildRun();
        printf("child quit ...\n");
        exit(123);
    }
    LoadTask();
    // father
    while(1)
    {
        int status = 0;
        pid_t rid = waitpid(id, &status, WNOHANG); // non block
        if(rid == 0)
        {
            usleep(100000);
            printf("child is running, father check next time!\n");
            DoOtherThing();
        }
        else if(rid > 0)
        {
            if(WIFEXITED(status))
            {
                printf("child quit success, child exit code : %d\n", WEXITSTATUS(status));
            }
            else
            {
                printf("child quit unnormal!\n");
            }
            break;
        }
        else
        {
            printf("waitpid failed!\n");
            break;
        }
    }

}

 

pid_t返回值 

设置了waitpid的WNOHANG后

  • 非阻塞等待会立刻返回,阻塞等待会等待子进程结束才会返回。
  • pit_t > 0 :等待成功,子进程退出了,并且父进程回收成功。
  • pit_t < 0 :等待失败。
  • pit_t == 0 :检测是成功的,只不过子进程还没退出,需要你下一次进行重复等待。

阻塞等待VS非阻塞等待

场景:张三找李四求助帮他复习期末考试。张三在李四的楼下等待李四就绪。

非阻塞等待:

  • 张三每隔几分钟就给李四打电话询问他是否就绪了
  • 张三在没有打电话的时间看书/游戏/抖音
  • 就绪的过程本质就是非阻塞等待。
  • 张三非阻塞等待李四过程 == 函数调用
  • 张三给李四打电话 == 函数传参
  • 李四说等着没好 == 函数的返回值
  • 每次函数调用的本质是检测李四的状态(是否就绪)
  • 立刻有返回值,多次等待,多次返回。
  • pid_ t waitpid(pid_t pid, int *status, WNOHANG);
  • pit_t == 0 :检测是成功的,只不过子进程还没退出,需要你下一次进行重复等待。
  • pit_t > 0 :等待成功,子进程退出了,并且父进程回收成功。
  • pit_t < 0 :等待失败。

阻塞等待:

  • 张三一直给李四打着电话,直到李四就绪,期间张三一直等待李四就绪,不敢别的事情。一直检测李四的状态(不就绪,就不返回)
  • 一直等待。直到子进程终止才返回。
  • pid_ t waitpid(pid_t pid, int *status, 0);
  • pit_t > 0 :等待成功,子进程退出了,并且父进程回收成功。
  • pit_t < 0 :等待失败。

🙂感谢大家的阅读,若有错误和不足,欢迎指正。下篇进入进程替换专题。

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

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

相关文章

C++容器之vector类

目录 1.vector的介绍及使用1.1vector的介绍1.2vector的使用1.2.1 vector的定义1.2.2 vector iterator 的使用1.2.3 vector 空间增长问题1.2.4 vector 增删查改1.2.5vector 迭代器失效问题1.2.6 vector 在OJ中的使用。 2.vector深度剖析及模拟实现2.1 std::vector的核心框架接口…

金三银四面试题(二十五):策略模式知多少?

什么是策略模式 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;旨在定义一系列算法&#xff0c;将每个算法封装到一个独立的类中&#xff0c;使它们可以互换。策略模式让算法的变化独立于使用它们的客户端&#xff0c;使得客户端可以根据…

车载测试系列:入行车载测试分享

车载测试前景如何&#xff1f; 软件定义汽车时代的发展趋势&#xff0c;随着控制器自主开发力度的加强&#xff0c;作为V流程中必备环节&#xff0c;车载测试工程师岗位需求会越来越多&#xff1b;控制器集成化&#xff0c;功能集成程度越来越高&#xff0c;对于测试工程师的知…

3. 初探MPI——(非阻塞)点对点通信

系列文章目录 初探MPI——MPI简介初探MPI——&#xff08;阻塞&#xff09;点对点通信初探MPI——&#xff08;非阻塞&#xff09;点对点通信初探MPI——集体通信 文章目录 系列文章目录前言一、Non-blocking communications1.1 Block version1.2 Non-blocking version 二、准…

思维导图软件哪个好?盘点这5款好用的工具!

思维导图作为一种有效的思维工具&#xff0c;在日常生活和工作中扮演着越来越重要的角色。无论是学习、工作规划&#xff0c;还是项目管理&#xff0c;思维导图都能帮助我们更好地组织思路&#xff0c;提升工作效率。然而&#xff0c;市面上众多的思维导图软件让人眼花缭乱&…

软件系统工程建设全套资料(交付清单)

软件全套精华资料包清单部分文件列表&#xff1a; 工作安排任务书&#xff0c;可行性分析报告&#xff0c;立项申请审批表&#xff0c;产品需求规格说明书&#xff0c;需求调研计划&#xff0c;用户需求调查单&#xff0c;用户需求说明书&#xff0c;概要设计说明书&#xff0c…

C++类和对象(4)

目录 1.初始化列表 2.单参数里面的隐式类型转换 3.多参数的隐式类型转换 4.匿名对象 1.初始化列表 &#xff08;1&#xff09;首先看一下初始化列表具体是什么&#xff1f; 这个就是初始化列表的具体形式&#xff0c;对&#xff0c;你没有看错&#xff0c;这个初始化列表里…

python:画折线图

import pandas as pd import matplotlib.pyplot as plt from matplotlib.font_manager import FontProperties# 设置新宋体字体的路径 font_path D:/reportlab/simsun/simsun.ttf# 加载新宋体字体 prop FontProperties(fnamefont_path)""" # 读取 xlsx 文件 d…

【投资必看】充电桩加盟合作哪家好,充电桩厂家合作模式一般有哪些?

随着新能源汽车行业的蓬勃发展&#xff0c;充电桩作为关键的基础设施&#xff0c;其市场需求日益增长。对于有意进入这一行业的投资者来说&#xff0c;了解和选择适合的合作模式至关重要。充电桩厂家的合作模式一般有哪些&#xff0c;本文将从设备销售和投资运营两个维度进行讨…

容灾演练双月报|郑大一附院数据级容灾演练切换

了解更多灾备行业动态 守护数字化时代业务连续 目录 CONTENTS 01 灾备法规政策 02 热点安全事件 03 容灾演练典型案例 01 灾备法规政策 3月19日&#xff0c;工信部发布《工业和信息化部办公厅关于做好2024年信息通信业安全生产和网络运行安全工作的通知》。明确提出“…

官宣:vAsterNOS正式发布!开放网络操作系统免费试用!

近期&#xff0c;vAsterNOS&#xff08;设备模拟器&#xff09;正式发布&#xff0c;可以满足用户快速了解 AsterNOS、体验实际操作、搭建模拟网络的需求&#xff0c;可运行在GNS3、EVE-NG等网络虚拟软件中。 AsterNOS 网络操作系统是星融元为人工智能、机器学习、高性能计算、…

java培训班还值得去培训吗?

请大家关注我的公众号&#xff1a;老胡聊Java 1 应届生或者在校生&#xff0c;如果感觉有必要&#xff0c;可以去提升下技术&#xff0c;因为应届生或在校生找工作时&#xff0c;未必要提升真实项目经验&#xff0c;所以用应届生身份学到的spring boot等java技术背面试题&#…

《二十三》Qt 简单小项目---视频播放器

QT 使用QMediaPlayer实现的简易视频播放器 效果如下&#xff1a; 功能点 播放指定视频点击屏幕暂停/播放开始/暂停/重置视频拖拽到指定位置播放 类介绍 需要在配置文件中加入Multimedia, MultimediaWidgets这俩个库。 Multimedia&#xff1a;提供了一套用于处理音频、视频…

如何开启深色模式【攻略】

如何开启深色模式【攻略】 前言版权推荐如何开启深色模式介绍手机系统手机微信手机QQ手机快手手机抖音 电脑系统电脑微信电脑QQ电脑WPS电脑浏览器 最后 前言 2024-5-9 20:48:21 深色模式给人以一种高级感。 本文介绍一些常用软件深色模式的开启 以下内容源自《【攻略】》 仅…

基于Spring Boot的酒店管理系统设计与实现

基于Spring Boot的酒店管理系统设计与实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 系统首页界面图&#xff0c;在系统首页可以查看首页…

【数据结构-二叉搜索树的增删查改】

&#x1f308;个人主页&#xff1a;努力学编程’ ⛅个人推荐&#xff1a;基于java提供的ArrayList实现的扑克牌游戏 |C贪吃蛇详解 ⚡学好数据结构&#xff0c;刷题刻不容缓&#xff1a;点击一起刷题 &#x1f319;心灵鸡汤&#xff1a;总有人要赢&#xff0c;为什么不能是我呢 …

python-类和对象

1、设计一个 Circle类来表示圆,这个类包含圆的半径以及求面积和周长的函数。再使用这个类创建半径为1~10的圆,并计算出相应的面积和周长。 &#xff08;1&#xff09;源代码&#xff1a; import math class Circle: def __init__(self, r): self.r r #面积 def area(self): r…

最佳实践 | 八爪鱼采集器如何用PartnerShare做全民分销?

在数字化时代&#xff0c;数据采集和分析已经成为企业运营和决策的重要一环。八爪鱼采集器作为一款领先的SaaS产品&#xff0c;凭借其强大的数据采集和处理能力&#xff0c;成为了众多企业和个人用户的心头好。为了进一步拓展市场份额&#xff0c;提升品牌影响力&#xff0c;八…

TCP通信并发:

上次的程序只能保持&#xff0c;单线程或者进程 多进程并发服务器 进程的特点&#xff08;有血缘关系&#xff09; 创建子进程&#xff1a;fork&#xff08;&#xff09;&#xff1b; 虚拟地址空间被复制 &#xff0c;从一份变成两份&#xff08;用户区和内核区&#xff09…

国内如何访问 OpenAI 的 api

这个问题甚至我的一些大厂的朋友也不太清楚&#xff0c;所以我觉得有必备写一篇文章来简单盘盘它&#xff0c;希望能帮助到有需要的人 众所周知&#xff0c;由于大陆与 OpenAI 双方互相封锁&#xff0c;大陆是无法直接访问 OpenAI api 的 不过由于 GPT 4 的统治地位&#xff0c…
最新文章