当前位置: 首页 > news >正文

[Linux] 进程创建、退出和等待

标题:[Linux] 进程创建、退出和等待

个人主页@水墨不写bug

(图片来源于AI)

目录

一、进程创建fork()

1) fork的返回值:

2)写时拷贝

​编辑3)fork常规用法

4)fork调用失败的原因

二、什么是进程退出

1)exit()函数于系统调用接口_exit()有什么区别?

三、僵尸进程和进程等待

1)父进程处理僵尸进程就需要进程等待

2)阻塞等待 

3)非阻塞等待:

 4)输出型参数status:

 总结:


正文开始:

一、进程创建fork()

         fork()是Linux操作系统提供的系统调用,作用是从一个已经存在的进程中创建一个新进程。新进程为子进程,原进程为父进程。

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

 

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

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

        具体创建过程的内存图示见《Linux:初识进程地址空间》 ,子进程创建后这里仅仅给出一张图:

         最重要的是:当一个进程调用fork之后,就有两个二进制代码相同的进程。而且它们都运行到相同的地方。如下面的例子:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>int main()
{printf("fork之前 我的pid:%d\n",getpid());pid_t id = fork();printf("fork之后 我的pid:%d, fork的返回值:%d\n",getpid(),id);return 0;
}

        运行之后,结果如图:

         分析:

        在fork之前,只有一个进程,pid=48247;

        fork之后,父进程(pid=48247)创建出子进程(pid=48248):从父子进程的pid临近和fork给子进程的返回值为0,给父进程的返回值为子进程的pid可以看出来。

         fork之后,父子进程都执行到fork函数这一行,于是,fork之前的代码不会被执行,之后的代码会被父子进程各自执行一次

1) fork的返回值:

        给子进程返回0;

        给父进程返回子进程的pid;

        如果出错了,则子进程没有被创建出来,那么给仅有的一个进程(父进程)返回-1;

2)写时拷贝

        写时拷贝(copy-on-write)是一种内存管理技术,用于优化内存使用和提高性能。它是一种延迟拷贝的策略,在创建副本之前,共享资源将不会被复制。

        写时拷贝的原理是,当一个对象需要被拷贝时,不会立即进行拷贝操作。而是让新对象与原对象共享同一份资源。当其中一个对象修改了该资源时,才会将资源复制到新的对象上。这样可以减少内存的使用,避免了不必要的复制操作。

3)fork常规用法

        一个父进程希望复制自己,使父子进程同时执行不同的代码段。例如,父进程等待客户端请求,生成子进程来处理请求。

        一个进程要执行一个不同的程序。例如子进程从fork返回后,调用exec函数。(进程替换函数)

4)fork调用失败的原因

        系统中有太多的进程;

        实际用户的进程数超过了限制;


二、什么是进程退出

         我们在当初学习C语言的时候,经常会malloc空间,但是动态内存开辟是会有失败的时候,malloc的最保险的用法:

    int size = 10;int* arr = (int*)malloc(size*sizeof(int));if(arr == NULL){perror("malloc fail:");exit(-1);}

         如果malloc失败,通常是非常严重的错误,这个时候进程已经没有必要继续运行下去了,这时候选择打印错误信息,如果调用exit函数退出。

        上述的进程退出只是进程退出的一种场景,其实进程想要退出,无非只有三种场景

1)代码运行完毕;

2)结果正确代码运行完毕,结果不正确;

3)代码异常终止

         当一个进程退出,我们在Linux终端可以使用:

echo $?

         命令查看最近一次进程退出的退出码。

        如果最近的一个进程正常退出,返回值是0;

 一个进程退出有什么方式?其实无非就是:

        1)从main函数返回;

        2)调用: exit();

        3)调用系统调用接口:   _exit();

对于其他的退出方式,一般就是我们主动退出:ctrl+C;

或者遇到空指针,或者被断言断死,其实这些退出方式有一个统称:被系统的信号杀死。

1)exit()函数于系统调用接口_exit()有什么区别?

         这两个函数的最本质功能是一样的,都是让进程退出,但是exit() 函数是对系统调用_exit()函数的封装。

        _exit函数是系统调用,exit是C语言的库函数。

进程调用_exit()会直接退出,但是调用exit会在退出之前做一些善后的处理:

        1. 执行用户通过 atexit或on_exit定义的清理函数。

        2. 关闭所有打开的流,所有的缓存数据均被写入(刷新缓冲区)

        3. 调用_exit

三、僵尸进程和进程等待

        在Linux系统中,僵尸进程(Zombie Process)是指已经结束执行的进程,但是其父进程还没有对其进行完全的清理操作,导致进程的资源没有被释放。

        僵尸进程的产生是因为操作系统在进程结束时不会立即清理相关的资源,而是会将其转变为僵尸进程,等待父进程来处理。父进程需要通过调用wait()或waitpid()系统调用来获取子进程的退出状态,并对其进行清理,释放相应的资源。如果父进程没有处理僵尸进程,那么僵尸进程会一直存在于系统中,占用系统资源。

        僵尸进程通常不会对系统造成直接的危害,因为它们已经停止运行。然而,如果有大量的僵尸进程存在,会浪费系统的进程表资源,并可能导致进程表耗尽的问题。此外,僵尸进程也可能是父进程出现问题或错误的一个指示,比如父进程无法正确处理子进程的退出状态。

1)父进程处理僵尸进程就需要进程等待

        父进程需要调用wait()/waitpid()等方法等待子进程退出。

2)阻塞等待 

        接口wait():等待任意一个子进程退出,但是在等待的过程中父进程什么事都干不了,这样的等待称为“阻塞等待”。

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

如果想要让父进程在等待的过程中做一些事情,就需要另一个接口:waitpid()

//头文件
#include<sys/types.h>
#include<sys/wait.h>pid_ t waitpid(pid_t pid, int *status, int options);//返回值:
//当正常返回的时候waitpid返回收集到的子进程的进程pid;//如果设置了选项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

3)非阻塞等待:

        waitpid()接口如果设置了MNOHANG,那么进程走到这个接口之后,会查看一次子进程是否已经退出,如果已经退出,我们就可根据此时的返回值设置循环的出口;

        如果没有退出,则进程会执行waitpid() 之后的代码逻辑,直到下一次循环再次到达waitpid()这个接口处,再次查看,继续循环。

非阻塞等待实例:


void oper()
{sleep(1);printf("等待不妨碍做其他事\n");
}int main()
{pid_t id = fork();if(id == 0){printf("我是子进程,5秒后退出\n");sleep(5);exit(0);}else{int status = 0;printf("我是父进程,等待子进程退出\n");while(1){pid_t rid = waitpid(id,&status,WNOHANG);if(rid > 0){printf("父进程等到子进程退出\n");break;}oper();}}return 0;
}

运行结果:

 4)输出型参数status:

        什么是输出型参数:输出型参数就是我们穿一个参数,他的值是由操作系统填充的,因此我们在传参的时候需要传地址

        如果传递NULL,表示不关心子进程的退出状态信息。

        如果传递了status的地址,操作系统会根据该参数,将子进程的退出信息反馈给父进程。

        status不能简单的当作整形来看待,需要当作位图来看待,具体细节如下图(status是32位整形,高16位并不携带信息,只有status低16比特位携带信息):

 对于低16位:

        如果正常退出(没有被信号杀掉):那么低8位为0,次低8位表示退出码,这里的退出码,就是函数return的返回值,也是exit()括号内传的值。退出信号的意义是由我们自己赋予的。

        如果异常退出(进程被信号杀掉):退出码虽然可以手动获得,但是已经没有意义了,因为已经发生重大错误,导致进程都没有执行完就退出了 。这时低7位表示进程的退出信号,也就是操作系统发送给进程的异常信号。第8位暂时不考虑。

        低7位正好是2的七次方:64个标识,正好对应kill命令给进程发送的终止信号的个数:

 

 总结:

        正常退出,次低8位 退出码;

        异常退出,低7位 退出信号;

其实,为了便于记忆,有两个专门对status处理的

        

WIFEXITED:

        如果子进程正常退出,返回真;

WEXITSTATUS:

        返回status的次低8位退出码。

实例:


int main()
{pid_t id = fork();if(id == 0){int* p = NULL;*p = 10;exit(0);}else{int status = 0;wait(&status);printf("%d\n",status);if(WIFEXITED(status)){printf("程序正常退出:%d\n",WEXITSTATUS(status));}else{printf("程序挂了:%d\n",(status&0x7f));}}return 0;
}

运行结果:


完~

未经作者同意禁止转载 

相关文章:

[Linux] 进程创建、退出和等待

标题&#xff1a;[Linux] 进程创建、退出和等待 个人主页水墨不写bug &#xff08;图片来源于AI&#xff09; 目录 一、进程创建fork&#xff08;&#xff09; 1&#xff09; fork的返回值&#xff1a; 2&#xff09;写时拷贝 ​编辑3&#xff09;fork常规用法 4&#xff…...

微软推出针对个人的 “AI伴侣” Copilot 会根据用户的行为模式、习惯自动进化

微软推出了为每个人提供的“AI伴侣”Copilot&#xff0c;它不仅能够理解用户的需求&#xff0c;还能根据用户的日常习惯和偏好进行适应和进化。帮助处理各种任务和复杂的日常生活场景。 它能够根据用户的生活背景提供帮助和建议&#xff0c;保护用户的隐私和数据安全。Copilot…...

【QT】QT入门

个人主页~ QT入门 一、简述QT1、什么是QT2、QT的优势3、应用场景 二、QT的基本使用1、新建项目&#xff08;1&#xff09;选择项目模版&#xff08;2&#xff09;选择项目路径&#xff08;3&#xff09;选择构建系统&#xff08;4&#xff09;填写类信息设置界面&#xff08;5&…...

Linux 6.11版本发布

Linux 6.11版本的发布是Linux社区的一个重要里程碑&#xff0c;它不仅在实时计算、性能优化方面取得了显著进展&#xff0c;还在安全性上迈出了关键一步。 一、实时计算与性能优化 1.io_uring子系统支持 Linux 6.11引入了io_uring子系统的增强功能&#xff0c;特别是支持了b…...

CSS 参考手册

CSS 参考手册 概述 CSS(层叠样式表)是一种用于描述HTML或XML文档样式的样式表语言。它用于控制网页的布局和外观,使网页设计更加美观和响应式。CSS可以定义文本颜色、字体、布局、响应式设计等,是网页设计和开发中不可或缺的一部分。 基础语法 CSS的基本语法由选择器和…...

数据采集工具sqoop介绍

文章目录 什么是sqoop?一、Sqoop的起源与发展二、Sqoop的主要功能三、Sqoop的工作原理四、Sqoop的使用场景五、Sqoop的优势六、Sqoop的安装与配置 sqoop命令行一、Sqoop简介与架构二、Sqoop特点三、Sqoop常用命令及参数四、使用示例五、注意事项 什么是sqoop? Sqoop是一款开…...

扫盲:写给UI设计师的SCADA系统知识点

一、SCADA是什么&#xff0c;及其组成。 SCADA&#xff08;Supervisory Control And Data Acquisition&#xff0c;监控与数据采集系统&#xff09;是一种用于实时监控、控制和数据采集的自动化系统。 SCADA的组成部分&#xff1a; - 人机界面&#xff08;HMI*&#xff1a;提…...

类的特殊成员函数——三之法则、五之法则、零之法则

系统中的动态资源、文件句柄&#xff08;socket描述符、文件描述符&#xff09;是有限的&#xff0c;在类中若涉及对此类资源的操作&#xff0c;但是未做到妥善的管理&#xff0c;常会造成资源泄露问题&#xff0c;严重的可能造成资源不可用。或引发未定义行为&#xff0c;进而…...

计算机毕业设计 智慧物业服务系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…...

Python软体中使用SpaCy进行命名实体识别

Python软体中使用SpaCy进行命名实体识别 命名实体识别(Named Entity Recognition,NER)是自然语言处理(NLP)中的一个重要任务,它涉及识别文本中的命名实体,例如人名、地名、组织名等。SpaCy是一种流行的NLP库,提供了高效的NER功能。在本文中,我们将介绍如何使用SpaCy进…...

华为云技术深度解析:以系统性创新加速智能化升级

华为云技术深度解析&#xff1a;以系统性创新加速智能化升级 在当今数字化转型的浪潮中&#xff0c;云计算作为关键的基础设施&#xff0c;正以前所未有的速度推动着各行各业的智能化升级。作为全球领先的云服务提供商&#xff0c;华为云凭借其深厚的技术积累和创新实力&#…...

推理攻击-Python案例

1、本文通过推理攻击的方式来估计训练集中每个类别的样本数量、某样本是否在训练集中。 2、一种简单的实现方法&#xff1a;用模型对训练数据标签进行拟合&#xff0c;拟合结果即推理为训练集中的情况。 3、了解这些案例可以帮助我们更好的保护数据隐私。 推理攻击&#xff08;…...

find_box_3d

参数 &#xff08;ObjectModel3DScene, SideLen1, SideLen2, SideLen3, MinScore, GenParam : GrippingPose, Score, ObjectModel3DBox, BoxInformation) 入参介绍 1&#xff0c;ObjectModel3DScene&#xff0c; 输入的3d模型&#xff0c;这个模型最好是由xyx三通道点…...

Visual Studio2017编译GDAL3.0.2源码过程

一、编译环境 操作系统&#xff1a;Windows 10企业版 编译工具&#xff1a;Visual Studio 2017旗舰版 源码版本&#xff1a;gdal3.0.2 二、生成解决方案 打开Visual Studio 2017的x64本机生成工具&#xff0c;切换到gdal3.0.2源码根目录&#xff1b;执行generate_vcxproj.b…...

计算机网络——email

pop3拉出来 超出ASCII码范围就不让传了 这样就可以传更大的文件...

【Linux】信号知识三把斧——信号的产生、保存和处理

目录​​​​​​​ 1、关于信号的前置知识 1.1.什么是信号&#xff1f; 1.2.为什么要学习信号&#xff1f; 1.3.如何学习信号&#xff1f; 1.4.一些常见的信号 1.5.信号的处理方式 1.6.为什么每一个进程都可以系统调用&#xff1f; 2.信号的产生 2.1.kill命令产生信号…...

【国庆要来了】基于Leaflet的旅游路线WebGIS可视化实践

前言 转眼2024年的国庆节马上就要来临了&#xff0c;估计很多小伙伴都计划好了旅游路线。金秋十月&#xff0c;不管是选择出门去看看风景&#xff0c;还是选择在家里看人。从自己生活惯了的城市去别人生活惯了的城市&#xff0c;去感受城市烟火、去感受人文风景&#xff0c;为2…...

Element-UI Plus 暗黑主题切换及自定义主题色

1. 暗黑主题切换 在main.js中引入下面文件 import element-plus/theme-chalk/dark/css-vars.css安装 vueuse/core pnpm add vueuse/coreApp.vue 添加下面代码 使用了 useDark() 的页面才会从 localStorage中读取当前主题状态&#xff0c;否则&#xff0c;刷新页面就会恢复默…...

人工智能与机器学习原理精解【31】

文章目录 卷积神经网络CNN定义数学原理与公式计算与定理架构例子例题 全连接层的前馈计算定义数学原理与公式计算过程示例 参考文献 卷积神经网络 CNN 即卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;&#xff0c;是一类包含卷积计算且具有深度结构的前…...

如何安全地大规模部署 GenAI 应用程序

大型语言模型和其他形式的生成式人工智能(GenAI) 的广泛使用带来了许多组织可能没有意识到的安全风险。幸运的是&#xff0c;网络和安全提供商正在寻找方法来应对这些前所未有的威胁。 随着人工智能越来越深入地融入日常业务流程&#xff0c;它面临着泄露专有信息、提供错误答…...

2026年主流抓娃娃App大对比,哪个才是你的“抓宝神器”?

在当今快节奏的生活中&#xff0c;年轻人面临着来自学业、工作、社交等多方面的压力。为了缓解这些压力&#xff0c;寻找适合的解压方式成为了大家的共同需求。抓娃娃App作为一种新兴的娱乐方式&#xff0c;正逐渐受到年轻人的喜爱。下面我们就从潮流趋势、科技前沿、行业洞察等…...

Halcon深度学习工具(DLT)安装与中文环境配置实战

1. Halcon DLT安装前的准备工作 第一次接触Halcon深度学习工具(DLT)时&#xff0c;我完全被各种专业术语搞晕了。后来才发现&#xff0c;只要做好前期准备&#xff0c;安装过程其实比想象中简单得多。首先需要确认的是你的Windows系统版本&#xff0c;DLT目前支持Windows 10和1…...

GARbro:跨平台视觉小说游戏资源解析与提取工具

GARbro&#xff1a;跨平台视觉小说游戏资源解析与提取工具 【免费下载链接】GARbro Visual Novels resource browser 项目地址: https://gitcode.com/gh_mirrors/ga/GARbro GARbro是一款专门用于解析和提取视觉小说游戏资源文件的跨平台开源工具&#xff0c;支持数百种游…...

终极指南:如何使用Autoclick实现Mac自动点击900次/秒

终极指南&#xff1a;如何使用Autoclick实现Mac自动点击900次/秒 【免费下载链接】Autoclick A simple Mac app that simulates mouse clicks 项目地址: https://gitcode.com/gh_mirrors/au/Autoclick 你是否厌倦了重复性的鼠标点击工作&#xff1f;无论是游戏中的重复操…...

从零构建现代化Web控制面板:安全架构与实时监控实践

1. 项目概述&#xff1a;一个为开发者设计的现代化控制面板最近在GitHub上看到一个挺有意思的项目&#xff0c;叫clawpanel&#xff0c;作者是kweephyo-pmt。光看名字&#xff0c;你可能会联想到“爪子”和“面板”&#xff0c;感觉像是个带点攻击性或工具属性的管理界面。实际…...

QMCFLAC2MP3终极指南:免费快速解锁QQ音乐格式限制

QMCFLAC2MP3终极指南&#xff1a;免费快速解锁QQ音乐格式限制 【免费下载链接】qmcflac2mp3 直接将qmcflac文件转换成mp3文件&#xff0c;突破QQ音乐的格式限制 项目地址: https://gitcode.com/gh_mirrors/qm/qmcflac2mp3 你是否曾经在QQ音乐下载了心爱的歌曲&#xff0…...

开源自动驾驶系统终极指南:从入门到精通

开源自动驾驶系统终极指南&#xff1a;从入门到精通 【免费下载链接】openpilot openpilot is an operating system for robotics. Currently, it upgrades the driver assistance system on 300 supported cars. 项目地址: https://gitcode.com/GitHub_Trending/op/openpilo…...

从开源AI导师项目GURU-Ai拆解:如何构建具备教学能力的智能体

1. 项目概述&#xff1a;一个“AI导师”的诞生与定位最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“Guru322/GURU-Ai”。光看名字&#xff0c;你可能会觉得这又是一个平平无奇的AI工具仓库。但点进去细看&#xff0c;你会发现它的野心不小——它想做的不是又一个聊天机…...

Nixtla时间序列预测库实战:从统计模型到深度学习的一站式解决方案

1. 项目概述&#xff1a;时间序列预测的“瑞士军刀”如果你正在处理销售预测、服务器负载监控或者任何与时间相关的数据预测问题&#xff0c;并且厌倦了在复杂的模型库和繁琐的预处理步骤之间反复横跳&#xff0c;那么 Nixtla 这个开源项目很可能就是你一直在找的“瑞士军刀”。…...

基于双线性插值的AMG8833热成像分辨率提升方案与嵌入式实现

1. 项目概述&#xff1a;从8x8到15x15&#xff0c;一次软件驱动的热成像分辨率革命如果你玩过基于AMG8833这类低成本红外热成像传感器的项目&#xff0c;大概率会对它那8x8的“马赛克”图像印象深刻——64个像素点&#xff0c;勉强能看出个温度轮廓&#xff0c;但细节&#xff…...