Linux系统编程(多进程编程深入1)

news2024/10/6 12:35:25

文章目录

  • 前言
  • 一、进程参数和环境变量的意义
  • 二、子进程程序结束返回值到哪里去了?
  • 三、进程退出函数
  • 四、实际使用案例
  • 五、僵尸进程
  • 总结


前言

本篇文章我们深入的讲解多进程编程。

一、进程参数和环境变量的意义

进程参数和环境变量是两种不同的机制,但它们都在操作系统中扮演着重要的角色。它们用于传递信息给正在运行的进程,以影响它们的行为和配置。

进程参数(Process Arguments):
进程参数是在启动进程时传递给它的命令行参数。它们是在运行进程时指定的,并且可以用于向程序提供特定的输入或配置信息。进程参数通常以空格分隔,并作为命令行命令的一部分传递给可执行文件。

进程参数的意义:

向程序传递输入:可以通过命令行参数向程序传递不同的输入数据,以便程序根据不同的参数执行不同的操作或处理不同的数据。
配置程序行为:可以使用进程参数来配置程序的行为,例如设置日志级别、指定文件路径、设定运行模式等。

示例:

   $ ./my_program arg1 arg2 --option=value

环境变量(Environment Variables):
环境变量是在操作系统中设置的全局变量,可以被所有运行的进程访问。它们是键值对的形式,其中键是环境变量的名称,值是环境变量的内容。环境变量提供了一种在进程之间共享配置和信息的机制。

环境变量的意义:

配置系统参数:环境变量可以用于配置整个系统的行为,例如设置默认的语言、指定默认的编译器、定义系统路径等。
程序运行时的配置:程序可以读取环境变量来进行特定的配置,例如读取数据库连接信息、API密钥等。
进程通信:在多进程或多线程的场景中,环境变量可以作为通信媒介,在进程之间传递信息。

示例:

   $ export MY_VAR="Hello World"

通过使用进程参数和环境变量,我们可以在不修改程序代码的情况下,通过外部的输入和配置来改变进程的行为和属性。这是一种灵活和可定制的机制,使我们能够根据需要对程序进行动态的调整和配置。

二、子进程程序结束返回值到哪里去了?

当子进程程序结束时,其返回值会被传递给父进程。父进程可以通过一些机制来获取子进程的返回值,这样可以对子进程的执行结果进行处理。

一种常见的获取子进程返回值的方法是使用系统调用wait()或waitpid()。这些调用会使父进程等待子进程的结束,并获取子进程的返回值。父进程可以通过这个返回值来了解子进程的执行状态,通常返回值为一个整数,用于表示子进程的退出状态。

在父进程中,可以使用以下方法来获取子进程的返回值:

1.使用wait()系统调用:

wait()函数用于使父进程等待其子进程结束,并获取子进程的终止状态。当调用wait()函数时,父进程会暂停执行,直到一个子进程结束。

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);

wait()函数的参数是一个指向整型的指针status,用于获取子进程的退出状态。通过该指针,父进程可以获取子进程的退出状态码,以判断子进程的执行结果。

wait()函数会阻塞父进程的执行,并等待一个子进程终止。当子进程终止后,父进程会继续执行,并返回被终止的子进程的进程ID。同时,子进程的退出状态码会存储在status指针所指向的位置。

#include <sys/types.h>
#include <sys/wait.h>
...
int status;
pid_t child_pid = wait(&status);
if (WIFEXITED(status)) {
    int exit_status = WEXITSTATUS(status);
    // 处理子进程的退出状态
}

2.使用waitpid()系统调用:

waitpid()函数可以用于等待指定的子进程结束,并获取其终止状态。该函数也可以用于处理多个子进程的情况。

#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);

waitpid()函数的第一个参数pid指定了要等待的子进程的进程ID。如果pid为负值,那么waitpid()会等待任意子进程终止。如果pid为0,则等待与调用者位于同一进程组的任意子进程。如果pid为正值,则等待具有指定进程ID的子进程。

waitpid()函数的第二个参数status用于获取子进程的退出状态码。第三个参数options指定额外的选项,比如WNOHANG表示不阻塞父进程,而是立即返回。

waitpid()函数会阻塞父进程的执行,直到指定的子进程终止。当子进程终止后,父进程会继续执行,并返回被终止的子进程的进程ID。同时,子进程的退出状态码会存储在status指针所指向的位置。

#include <sys/types.h>
#include <sys/wait.h>
...
int status;
pid_t child_pid = waitpid(child_pid, &status, 0);
if (WIFEXITED(status)) {
    int exit_status = WEXITSTATUS(status);
    // 处理子进程的退出状态
}

在这些方法中,status变量用于存储子进程的退出状态,可以使用宏WIFEXITED(status)来判断子进程是否正常退出,WEXITSTATUS(status)则可以获取子进程的退出状态值。

需要注意的是,子进程的返回值范围通常是一个字节,即0-255之间的整数。如果子进程需要返回更多信息,可以使用其他机制,例如通过标准输出或文件来传递额外的数据。

三、进程退出函数

当一个进程完成其任务或者发生了错误时,可以使用进程退出函数来终止进程的执行。两个常用的进程退出函数是exit()和abort()。

1.exit()
exit()函数用于正常终止进程的执行。它接受一个整数参数作为进程的退出状态码,并将控制返回给操作系统。这个状态码可以被其他进程或者父进程通过调用wait()或waitpid()来获取。

#include <stdlib.h>
void exit(int status);

exit()函数会执行以下操作:

调用通过atexit()函数注册的退出处理程序(exit handlers)。

关闭已打开的文件描述符。

刷新标准I/O缓冲区。

解除所有由进程分配的内存。

返回到操作系统,并传递退出状态码。

退出状态码可以是任意的整数值,一般情况下非零的状态码表示进程执行失败,而0表示成功。

2.abort()
abort()函数用于异常终止进程的执行。当调用abort()函数时,进程会向操作系统发送终止信号(SIGABRT),导致进程异常终止。与exit()函数不同,abort()函数不接受任何参数。

#include <stdlib.h>
void abort(void);

abort()函数会执行以下操作:

强制将进程终止,不执行后续的代码。

调用通过atexit()函数注册的退出处理程序。

使用默认的终止信号(SIGABRT)向操作系统发送终止请求。

abort()函数通常用于处理严重错误或异常情况,例如发生内存错误或者其他无法恢复的错误。它会生成一个包含调试信息的core dump文件,方便开发人员进行调试和错误分析。

总结:exit()函数用于正常终止进程的执行,而abort()函数用于异常终止进程的执行。它们在进程退出时执行不同的操作,但都是用于终止进程的执行。

四、实际使用案例

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

int main(int argc, char** argv, char** envp)
{
    pid_t pid = 0;
    int a = 1;
    int b = 0;
    int status = 0;

    printf("parent :%d\n", getpid());

    if((pid = fork()) == 0) exit(0);

    printf("child = %d\n", pid);

    if((pid = fork()) == 0) abort();

    printf("child = %d\n", pid);

    if((pid = fork()) == 0) a / b, exit(1);

    printf("child = %d\n", pid);

    sleep(20);

    while((pid = wait(&status)) > 0)
    {
        printf("child pid :%d status :%d\n", pid, status);
    }    

    return 0;
}

运行代码后使用ps查看进程情况:
在这里插入图片描述

sleep后再查看进程情况:
在这里插入图片描述
为什么延时后被创建出来的线程就不见了呢,我们下面来讲解。

五、僵尸进程

当一个进程终止时,它的一部分信息需要被保留,以便父进程在需要时查询和处理该子进程的退出状态。此时,子进程变成了一种中间状态,称为"僵尸进程"(Zombie process)或"defunct"进程。

僵尸进程的产生主要是因为父进程没有及时处理子进程的退出状态。在父进程调用wait()或waitpid()等函数之前,子进程的进程描述符和一些资源(如打开的文件描述符)都被维护在系统中,以备父进程查询使用。

僵尸进程的存在不是一个严重的问题,因为内核会回收子进程其他的资源(如内存),但僵尸进程会占用一定的系统资源(主要是进程表项),如果过多的僵尸进程积累,可能会消耗过多的系统资源。

解决僵尸进程的常见方法是父进程及时处理子进程的退出状态,即调用wait()或waitpid()等函数来回收子进程的资源,并从进程表中删除子进程的记录。这样子进程就会完全终止并从系统中清除。

有时,如果父进程已经终止,或者父进程没有合适的处理子进程的代码,僵尸进程可能会长时间存在。在这种情况下,可以通过重新启动父进程、修复父进程的代码或使用一些系统工具来清除僵尸进程。

总结:僵尸进程是指已经终止的子进程,但其父进程尚未及时处理子进程的退出状态。它们处于一种临时的中间状态,不再执行任何代码,但仍然占用一些系统资源。及时处理子进程的退出状态是预防和解决僵尸进程问题的关键。

总结

本篇文章就讲解到这里,下一篇文章我们继续分析多进程编程。

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

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

相关文章

SuperMap GIS基础产品桌面GIS FAQ集锦(3)

SuperMap GIS基础产品桌面GIS FAQ集锦&#xff08;3&#xff09; 【iDesktop】如何获取倾斜摄影的边界线&#xff1f; 【解决办法】1、将倾斜摄影添加到球面场景&#xff0c;使用【三维分析】-【生成DSM】获取栅格数据集 2、使用【代数运算】功能&#xff0c;将大于0的栅格值统…

我做了10年的测试,由衷的建议年轻人别入这行了

两天前&#xff0c;有个做功能测试7年的同事被裁员了。这位老哥已经做到了团队中的骨干了&#xff0c;人又踏实&#xff0c;结果没想到刚刚踏入互联网“老龄化”大关&#xff0c;就被公司给无情优化了。 现在他想找同类型的工作&#xff0c;薪资也一直被压&#xff0c;考虑转行…

java(SpringBoot)中操作Redis的两种方式

前言 之前我们介绍过了redis的五中基本类型以及在可视化界面进行操作&#xff0c;那么在开发中&#xff08;在代码中&#xff09;我们通常使用&#xff0c;jedis进行操作redis,要是springboot 项目&#xff0c;我们通常使用redisTemplte进行操作 首先将redis启动 方式一 Jred…

smart Java——Netty实战(上):select/poll/epoll、NIOReactor模型

文章目录 1.多路复用——select、poll、epoll底层原理2.NIOReactor模型&#xff08;1&#xff09;单Reactor单线程模型&#xff08;2&#xff09;单Reactor多线程模型&#xff08;3&#xff09;主从Reactor多线程模型&#xff08;Netty&#xff09; 3.Netty核心组件&#xff08…

备战金九银十,互联网大厂1000道java高频面试知识点(附答案,赶紧收藏)

Java 面试八股文有必要背吗&#xff1f; 我的回答是&#xff1a;很有必要。你可以讨厌这种模式&#xff0c;但你一定要去背&#xff0c;因为不背你就进不了大厂。现如今&#xff0c;Java 面试的本质就是八股文&#xff0c;把八股文面试题背好&#xff0c;面试才有可能表现好。…

卷积实现—im2col+gemm

普通卷积 看卷积的实现&#xff0c;先看其普通的计算方式&#xff1a;滑窗计算和其计算shape大小的公式&#xff0c;以及各个卷积特性对其计算的影响&#xff0c;比如&#xff1a;stride&#xff0c;group&#xff0c;dilation&#xff0c;pad等。 H o u t ( H i n − k h p …

OpenGL 帧缓冲

1.简介 我们已经使用了很多屏幕缓冲了&#xff1a;用于写入颜色值的颜色缓冲、用于写入深度信息的深度缓冲和允许我们根据一些条件丢弃特定片段的模板缓冲。这些缓冲结合起来叫做帧缓冲(Framebuffer)&#xff0c;它被储存在内存中。OpenGL允许我们定义我们自己的帧缓冲&#x…

Fiddler不仅可以抓包,还可以做接口测试喔

前言 Fiddler最大的优势在于抓包&#xff0c;我们大部分使用的功能也在抓包的功能上&#xff0c;Fiddler做接口测试也是非常方便的。对应没有接口测试文档的时候&#xff0c;可以直接抓完包后&#xff0c;copy请求参数&#xff0c;修改下就可以了。 Composer简介 点开右侧Co…

模拟电路系列分享-晶体管的四种状态

目录 概要 整体架构流程 技术名词解释 1.截止状态 2.放大状态 3.饱和状态 4.倒置状态 技术细节 小结 概要 提示&#xff1a;这里可以添加技术概要 晶体管有4种工作状态&#xff0c;分别是截止、放大、饱和&#xff0c;以及倒置。 整体架构流程 提示&#xff1a;这里可以添加…

黑马程序员前端 Vue3 小兔鲜电商项目——(九)购物车

文章目录 本地购物车添加购物车头部购物车模板代码渲染数据 删除功能实现购物车统计信息列表购物车-基础内容渲染模版代码路由配置渲染列表 列表购物车-单选功能实现列表购物车-全选功能实现列表购物车-统计数据功能实现 接口购物车加入购物车删除购物车 退出登录-清空购物车购…

Matplotlib - 绘制 带有对角线的散点图 (Diagonal Scatter Plots) 函数源码

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131384440 Matplotlib 是一个用于绘制二维图形的 Python 库&#xff0c;提供了一个 pyplot 模块&#xff0c;用于创建各种类型的图表。其…

实战经验---好用的Midjourney提示词

说明&#xff1a;本文基于Midjourney&#xff08;下称MJ&#xff09;官方说明书整理&#xff0c;分2篇文章发布&#xff0c;这是第1篇。内容主要包括绘画指令&#xff08;Prompt&#xff09;、提示、参数、设置、模型选择等。 由于是整理文本&#xff0c;过程中个别地方为了显…

应对流量损耗:提升APP广告变现效果的关键策略!

​引言&#xff1a; 在APP广告变现的过程中&#xff0c;流量损耗是一个常见的问题&#xff0c;它不可避免地会发生。尽管开发者可以在合理的范围内承受这种损耗&#xff0c;但如果出现大范围的损耗&#xff0c;那就意味着在广告变现过程中出现了一些问题&#xff0c;限制了开发…

ThreadPoolExecutor的有参构造

核心要点 通过查看ThreadPoolExecutor里面的构造方法可以发现都是调用了方法参数最多的那个。 参数最多的构造方法展示 映入眼帘的是一些健壮性校验corePoolSize < 0&#xff1b;可以发现这个判断是核心线程的个数不能小于零。但是也就说明核心线程的个数可以等于零。maxim…

LLM - 搭建 DrugGPT 与药物分子领域结合的 ChatGPT 系统

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131384199 论文&#xff1a;DrugChat: Towards Enabling ChatGPT-Like Capabilities on Drug Molecule Graphs DrugChat&#xff0c;基…

【简单认识Nginx服务性能与安全优化】

文章目录 Nginx隐藏版本相关信息1.隐藏版本号2.修改版本号及相关信息 二、修改Nginx运行时的属主和属组三、配置Nginx网页缓存时间四、配置Nginx站点日志分割五、设置Nginx长连接及超时时间六、配置Nginx网页压缩七、配置Nginx防盗链1.模拟盗链2.配置防盗链并测试 Nginx隐藏版本…

【算法】数学相关知识总结

文章目录 gcd 和 lcm取模运算 %求一个点和一片矩形区域之间的最短距离 本文用于记录一些关于算法题中偶尔被使用到的数学相关知识。 gcd 和 lcm gcd 和 lcm 分别是 最大公约数&#xff08;Greatest common divisor&#xff09; 和 最小公因数&#xff08;Least Common Multip…

Nginx-redis【会话保持】

什么是会话保持 当用于登录一个网站服务器&#xff0c; 网站服务器会将用户的登录信息存储下来&#xff08;存储session&#xff09;&#xff0c;以保证我们能一直处于登录在线的状态 为什么要做会话保持 由于我们使用的是负载均衡轮询机制&#xff0c;会导致用户请求分散在…

nginx页面优化

文章目录 nginx页面优化一.nginx优化1.版本号1.1查看版本号1.2修改版本号1.2.1修改配置文件1.2.2修改源码文件&#xff0c;重新编译安装 2.nginx的日志分割2.1 写日志分割的脚本2.2给脚本执行权限、执行2.3创建定时任务可以每个月固定分割一次 3.nginx的页面压缩3.1配置3.2验证…

第1讲 Camera Sensor Driver课程简介

更多资源&#xff1a; 资源描述在线课程极客笔记在线课程知识星球星球名称&#xff1a;深入浅出Android Camera 星球ID: 17296815Wechat极客笔记圈 课程内容介绍 目标&#xff1a; 课程主要帮助大家理解camera sensor基本概念及原理知识&#xff0c;理解高通camera sensor驱…