Linux-进程控制(进程创建、进程终止、进程等待)

一、进程创建

1.1 fork函数介绍

        在命令行下我们可以通过 ./ + exe文件 来创建一个进程,通过fork函数,我们可以通过代码的形式从一个进程中创建一个进程,新进程为子进程,原进程为父进程,子进程在创建时,会与父进程共享下面的代码与数据,当数据被修改时,会采用写实拷贝的方式保证进程间的独立性。

//头文件
#include<unistd.h>//函数
pid_t fork()//返回值#子进程中返回0#父进程返回子进程id#出错返回-1

进程调用fork,当控制转移到内核中的fork代码后,内核做:

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

fork函数常规用法:

  • 一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请  求,生成子进程来处理请求。
  • 一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数

fork函数失败原因:

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制
     
1.2 使用举例
  #include<unistd.h>#include<stdio.h>#include<stdlib.h>int main(){//父进程printf("I am parent process ppid:%d pid:%d\n",getppid(),getpid());//创建子进程pid_t id=fork();//根据id的值分流,使父子进程执行不同的代码if(id == -1){exit(-1);}else if(id == 0){//子进程printf("I am child process ppid:%d pid:%d\n",getppid(),getpid());}else{                                                                                                                                                                                          //父进程printf("I am parent process ppid:%d pid:%d\n",getppid(),getpid());}return 0;}

二、进程终止

2.1 进程退出场景

  • 代码运行完毕,结果正确
  • 代码运行完毕,结果不正确
  • 代码没有运行完,发现异常,提前终止

 2.2 错误码与信号码

错误码
  • 在main函数中,我们通常会return 0,return -1等等,那这些数字有什么意义吗?
  //strerror可以查看错误码信息#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<string.h>                                                                                                                                                                           int main(){int i=0;for(i=0;i<255;i++){printf("%d:%s\n",i,strerror(i));}return 0;}

可以看到,不同的数字拥有不同的含义,0表示成功,非0表示错误,当程序执行完后,操作系统会检测到错误,并将错误信息打印出来,反馈给用户,这样就可以通过查看错误码来确定程序终止的情况,例如:

ps:操作系统中存在一个变量,名字就叫 ,它保存了最近一次进程的错误码,可以通过

echo $? 查看

信号码
  • 模拟野指针异常:
  int main()  {  int* p=NULL;*p=1;retrun 0;                                                                                                                                                                                  }  

  • 通过kill -11 给进程发信号

通过上述两个例子可以看出,异常终止也是因为OS给进程发了信号,让进程终止的

可以通过kill -l 查看所有信号

总结:

确认进程终止情况的方法:

1.先判断是否是异常导致

2.是异常通过查看信号码确定异常信息

3.不是异常直接看错误码确定错误信息即可

三、进程等待

3.1 进程等待的必要性
  • 子进程退出后,若父进程不进行管理,就会造成僵尸进程,会导致内存泄露问题
  • 父进程派给子进程的任务完成的如何,我们需要知道。如,子进程运行完成,结果对还是不对,或者是否正常退出
  • 父进程通过进程等待的方式,回收子进程资源,获取子进程退出信息
3.2 进程等待方法
3.2.1 wait
#include<sys/types.h>
#include<sys/wait.h>//等待任一个子进程
pid_t wait(int*status);#返回值:
成功返回被等待进程pid,失败返回-1。#参数:
输出型参数,获取子进程退出状态,不关心则可以设置成为NULL
  #include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>void ChildRun(){int cnt = 5;while(cnt){printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt    );sleep(1);cnt--;}}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(0);}// fahterpid_t rid = wait(NULL);if(rid>0){printf("wait success pid:%d\n",rid);}return 0;}
3.2.2 waitpid
//头文件: 
#include<sys/type.h>
#include<sys/wait.h>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非零,提取子进程退出码。(查看进程的退出码)

ps:WIFEXITED 与 WEXITSTATUS是两个宏

options:
WNOHANG(非阻塞等待): 若pid指定的子进程没有结束,则waitpid()函数返回0,不予以等待。若正常结束,则返回该子进程的ID。

  • pid = 0 ,子进程还没有退出,需要下一次再检测
  • pid > 0 ,  等待成功了,子进程退出,并且父进程回收成功
  • pid < 0 ,  等待失败
3.3 获取子进程status

        父进程要获取子进程的退出信息最重要的就是错误码与信号码,而进程PCB中会存在两个整形变量,用于保存错误码与信号码信息,操作系统可以根据wait与waitpid中status ,将子进程的信息传递给父进程

status不能简单的当作整形来看待,可以当作位图来看待,具体细节如下图(只研究status低16比特位):

  • 0-7位表示子进程的信号码(可让 status & 0x7F获取)
  • 8-15位表示子进程的错误码 (可让 (status >>8) & 0xFF获取 )

通过位运算获取错误码:

 #include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>void ChildRun(){int cnt = 5;while(cnt){printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt    );sleep(1);cnt--;}}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);}sleep(7);// fahter//pid_t rid = wait(NULL);                                                             int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){printf("wait success, rid: %d\n", rid);}else{printf("wait failed !\n");}sleep(3);printf("father quit, status: %d, child quit code : %d, child quit signal: %d\n", statu    s, (status>>8)&0xFF, status & 0x7F);}

通过宏获取错误码:

  #include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>void ChildRun(){int cnt = 5;while(cnt){ printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);sleep(1);cnt--;}}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);}sleep(7);// fahter//pid_t rid = wait(NULL);int status = 0;pid_t rid = waitpid(id, &status, 0);if(rid > 0){                                                                                                                                                                                        //判断子进程是否是因为异常退出if(WIFEXITED(status)){printf("wait success, child exit code:%d\n", WEXITSTATUS(status));//获取子进程退出码:123      }
}else{printf("child process quit unnormal!\n");}}else{printf("wait failed !\n");}sleep(3);printf("father quit, status: %d, child quit code : %d, child quit signal: %d\n", status, (status>>8)&0xFF, status & 0x7F);}

 

3.4 非阻塞等待 

        上述例子都是子进程正常退出的情况,属于阻塞等待,若子进程陷入死循环永远不退出,那么父进程就会一直待在waitpid函数体中,等待子进程退出,这段时间父进程什么事情也不能做,若给waitpid函数的options参数传入WNOHANG的话,此时等待就会变成非阻塞等待,父进程在等待子进程退出期间也可以做相关操作

  #include <stdio.h>#include <unistd.h>#include <string.h>#include <stdlib.h>#include <sys/types.h>#include <sys/wait.h>void DoanotherThing(){printf("I am doing anotherthing\n");}void ChildRun(){int cnt = 5;while(cnt){printf("I am child process, pid: %d, ppid:%d, cnt: %d\n", getpid(), getppid(), cnt);sleep(1);cnt--;}}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);}// fahterwhile(1)                                                                                                                                                                                 {int status = 0;pid_t rid = waitpid(id, &status, WNOHANG);if(rid==0){usleep(10000);printf("child is running ,check next time!\n");DoanotherThing();}else if(rid > 0){//判断子进程是否是因为异常退出if(WIFEXITED(status)){printf("wait success, child exit code:%d\n", WEXITSTATUS(status));//获取子进程退出码:123      }else{printf("child process quit unnormal!\n");}break;}else{printf("wait failed !\n");break;}}}

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

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

相关文章

教育建筑智慧能源管理平台解决方案【新型电力系统下的绿色校园能源管理平台】

一、行业特点 1.建筑类型多&#xff1a;集教学、科研、生活于一体&#xff0c;占地面积大&#xff0c;建筑类型多&#xff0c;功能划分复杂。 2.供电可靠性要求高&#xff1a;教育建筑中的高层建筑、图书馆、实验楼等特级和一级负荷比较多&#xff0c;一旦发生故障会危及生命…

STM32 ESP8266模块的曲折探索

这是本文的配套资料&#xff0c;最终工程请参考 新_ESP8266资料\stm32f103成功移植的项目 【免费】stm32f103c8t6esp8266资料资源-CSDN文库 一、等到了ready 产品参数 我使用的是ai-thinker的esp8266-01s&#xff0c;以下为产品规格书 引脚定义&#xff1a; 依据引脚定义&…

android studio忽略文件

右键文件&#xff0c;然后忽略&#xff0c;就不会出现在commit里面了 然后提交忽略文件即可

如何在VS Code上搭建 C/C++开发环境

顾得泉&#xff1a;个人主页 个人专栏&#xff1a;《Linux操作系统》 《C从入门到精通》 《LeedCode刷题》 键盘敲烂&#xff0c;年薪百万&#xff01; 一、什么是VScode VScode&#xff08;Visual Studio Code&#xff09;是一款由微软开发的免费开源的轻量级代码编辑器。它…

如何成功将自己开发的APP上架到应用商店

随着移动应用市场的蓬勃发展&#xff0c;开发一款优秀的APP已成为许多企业和个人的首要选择。然而&#xff0c;成功上架并有效推广APP至关重要。本文将逐步介绍完整的上架流程&#xff0c;包括准备所需材料、注册开发者账户、进行APP备案、提交审核以及上架成功后的推广和维护。…

电子商务营销中大数据分析|电商大数据采集API接口的应用

随着经济的不断发展&#xff0c;网络信息技术不断加强&#xff0c;电子商务和大数据的蓬勃发展极大地方便了人们的生活。本文章主要阐述大数据分析与电商营销的含义、大数据分析在电子商务营销中的应用&#xff0c;以及该应用的作用和存在哪些不足及解决方法。探究大数据分析在…

【MATLAB源码-第14期】基于matlab的2ASK的误码率BER仿真以及原信号调制信号解调信号波形展示。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 幅度偏移调制&#xff0c;又称幅移键控&#xff0c;幅度键移&#xff08;英语&#xff1a;Amplitude-shift keying&#xff0c;ASK&#xff09;是通过载波的幅度变化来表示数字信号的一种幅度调制方式。在一个ASK系统中&…

Nebula Graph-06-NebulaGraph Java 使用 和SpringBoot集成Nebula Graph

前言 系列文章&#xff1a; Nebula Graph-01-Nebula Graph简介和安装以及客户端连接 Nebula Graph-02-NebulaGraph高阶配置、用户管理、日志 Nebula Graph-03-NebulaGraph Studio-可视化web工具安装和使用 Nebula Graph-04-NebulaGraph nGQL的介绍和使用 Nebula Graph-05-Nebu…

【干货】Apache DolphinScheduler2.0升级3.0版本方案

升级背景 因项目需要使用数据质量模块功能&#xff0c;可以为数仓提供良好的数据质量监控功能。故要对已有2.0版本升级到3.0版本以上&#xff0c;此次选择测试了3.0.1 和 3.1.1 两个版本&#xff0c;对进行同数据等任务调度暂停等操作测试&#xff0c;最后选择3.0.1 版本 原因…

看漫画学Python:有趣好玩

书籍介绍 Python是一门既简单又强大的编程语言&#xff0c;被广泛应用于数据分析、大数据、网络爬虫、自动化运维、科学计算和人工智能等领域。Python也越来越重要&#xff0c;成为国家计算机等级考试科目&#xff0c;某些中小学也开设了Python编程课程。本书秉承有趣、有料、…

【linux网络(一)】初识网络, 理解四层网络模型

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux网络 1. 前言2. 初识网络…

Android开发简易登录界面

title: Android开发第四天 search: 2024-03-22 tags: Android开发 Android开发简易登录界面 文章目录 Android开发简易登录界面一、定义style样式二、完成 activity_main.xml 界面具体设计三、代码简述 背景 &#xff1a;在初学 android 开发的时候&#xff0c;为了尽量熟悉学…

使用下SAP HANA强大的Cloud控制台

前言 SAP的HANA数据库(注:这里指是云平台版本,不是platform的本地部署版本)的版本发布,基本上每个季度都有一次发布。2024年的第一个版本内部已经Release了,很快就会推到生产环境当中。当前要发布的版本是:2024.2.6 (QRC 1/2024)。而且每个版本的维护周期最长不会超过7…

Arduino+ESP8266+华为云物联网平台实现智能开关

前言 最近在做一个物联网项目&#xff0c;涉及到智能开关的开发。目前已经实现简单的TCP通信远程控制&#xff0c;但是考虑到后期的设备管理以及设备通信所需要的技术和服务器的维护成本&#xff0c;我决定将设备接入云平台。本文将详细阐述如何利用华为云的物联网平台&#x…

DB-GPT安装部署使用初体验

DB-GPT是什么&#xff1f;引自官网&#xff1a; DB-GPT是一个开源的AI原生数据应用开发框架(AI Native Data App Development framework with AWEL(Agentic Workflow Expression Language) and Agents)。 目的是构建大模型领域的基础设施&#xff0c;通过开发多模型管理(SMMF)、…

【ssh连接】奇奇怪怪报错记录

gitlab配置ssh连接&#xff0c;先跟着教程生成密钥&#xff0c;上传公钥&#xff0c;将服务器信息存入config文件&#xff0c;但是ssh连接超时&#xff0c;很急&#xff0c;想用服务器&#xff0c;各种搜索尝试&#xff0c;搞了两三天别的什么都没干&#xff0c;还是没解决&…

【Canvas与艺术】淡蓝辉光汽车速度仪表盘

【关键点】 内圈处渐变色的采用。 【效果图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>淡蓝辉光汽车速度仪表盘</t…

谈谈消息队列

这篇文章我们来聊聊消息队列。我一直在想&#xff0c;能不能用一篇文章就把消息队列的所有内容给串联起来。然后&#xff0c;之后每次看到这篇文章的时候&#xff0c;我就能够立马回忆起来这个大知识的所有知识点。所以我想尝试一下用这种长文的方式&#xff0c;将我自己对于消…

Ubuntu系统设置静态固定IP保姆级教程

1、查看网络接口信息 ifconfig 首先需要确认要设置固定IP的网络接口。在大多数情况下&#xff0c;这通常是ens33 2、查看路由网关信息 route -n # 查看打印 路由表 网关地址 3、备份文件 为了防止防止出现意外问题。Ubuntu中的网络配置文件通常存储在/etc/netplan/目录下&…

微服务概述

微服务 概述1.单体架构2.分布式架构3.微服务的架构特征&#xff1a; 服务拆分和远程调用提供者与消费者 概述 1.单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个包部署。 单体架构的优缺点如下&#xff1a; 优点&#xff1a; 架构…