【进程等待】阻塞等待 | 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.c1 #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   //father30   //父进程,父进程在子进程运行期间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         else48         {49           printf("child quit unnormal!\n");50         }51         printf("wait success,rid: %d\n",rid);52         break;53       }54       else55       {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){// childChildRun();printf("child quit ...\n");exit(123);}LoadTask();// fatherwhile(1){int status = 0;pid_t rid = waitpid(id, &status, WNOHANG); // non blockif(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.hqwc.cn/news/682194.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【随笔】Git 高级篇 -- 上传命令的参数 (下)git push(三十七)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

韩顺平0基础学Java——第4天

p45—p71 老天鹅&#xff0c;居然能中断这么久&#xff0c;唉...学不完了要 API API:application programing interface应用程序编程接口 www.matools.com 可以理解成Python的调包...c的头文件对吧 字符型 char用单引号 String用双引号 char本质上是个整数&#xff0c…

Zip压缩归档库-libzip介绍

1.简介 libzip是一个C库&#xff0c;用于读取、创建和修改zip格式的压缩文件。它支持从zip文件中读取、写入、添加和删除文件&#xff0c;还支持密码保护的zip文件。libzip是跨平台的&#xff0c;可以在多种操作系统上使用&#xff0c;包括Linux、Windows和macOS。 常用接口介…

python实验二 函数与类的应用

实验二 实验题目 1、请编写一个函数SDSearch(txt, word)&#xff0c;其中&#xff0c;txt是一段文本&#xff0c;word是给定的词汇&#xff0c;函数SDSearch可以找到word在txt中的所有位置&#xff0c;并将它们做为返回值返回&#xff0c;编写函数main()调用SDSearch(txt, wo…

Elastic 基于 RAG 的 AI 助手:利用 LLM 和私有 GitHub 问题分析应用程序问题

作者&#xff1a;来自 Elastic Bahubali Shetti 作为 SRE&#xff0c;分析应用程序比以往更加复杂。 你不仅必须确保应用程序以最佳状态运行以确保良好的客户体验&#xff0c;而且还必须了解某些情况下的内部工作原理以帮助排除故障。 分析基于生产的服务中的问题是一项团队运动…

[Linux]如何在Ubuntu 22.04系統安裝Node-red?

Node-red是一個建立在Node.js上的視覺化程式設計工具&#xff0c;其常見的應用情境為建置或轉換各項硬體之間的通信協定的物聯網或工聯網場域&#xff0c;其可藉由設置來安裝第三方應用模組來建置多樣的通信協定節點&#xff0c;包含modbus in/out, mqtt in/out, websocket in/…

NeRF算法

目录 算法介绍 基本原理 1. 体渲染 2. 多层感知机&#xff08;MLP&#xff09; 3. 位置编码 4. 两阶段层次化体采样 实验展示 代码解析 算法介绍 NeRF&#xff08;Neural Radiance Fields&#xff09;是一种用于从2D图像中重建3D场景的神经网络模型。它通过训练一个深度…

多态的原理

前言:以下的内容均是在VS2019的环境中&#xff0c;32位平台下的 目录 1.多态的实现条件 虚函数重写的两个例外 一个题加深理解 总结 重载 重写 重定义区别 2.多态的实现原理 单继承 多继承 动态多态和静态多态 多态的好问题 1.多态的实现条件 虚函数&#xff1a;被…

2-6 任务 猜数小游戏(单次版)

本任务要求编写一个猜数小游戏&#xff08;单次版&#xff09;&#xff0c;游戏规则是计算机产生一个0到100之间的随机整数&#xff0c;用户通过输入猜测的数字进行猜测&#xff0c;根据猜测情况给出提示&#xff0c;直到猜对为止。编程思路是利用while循环和多分支结构实现永真…

ESP-WROOM-32配置Arduino IDE开发环境

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、下载Arduino IDE二、安装工具集三、测试样例1.选则开发板2.连接开发板3.示例程序 四、使用官方示例程序总结 前言 之前用了很多注入STM32、树莓派Pico和Ar…

用Rust解决鸡兔同笼问题

目录 一、什么是鸡兔同笼问题&#xff1f; 二、用Rust解决鸡兔同笼问题 三、鸡兔同笼问题在实际生活中的应用有哪些&#xff1f; 一、什么是鸡兔同笼问题&#xff1f; 鸡兔同笼问题是一种古代著名的数学问题&#xff0c;用于训练逻辑思维和解决方程的能力。 鸡兔同笼问题起…

ssm105基于JAVAEE技术校园车辆管理系统+jsp

校园车辆管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园车辆管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…