[Linux]进程控制详解

news2025/2/23 6:28:12

1.创建进程

在这里插入图片描述
进程调用fork,当控制转移到内核中的fork代码后,内核做:
● 分配新的内存块和内核数据结构给子进程
● 将父进程部分数据结构内容拷贝至子进程
● 添加子进程到系统进程列表当中
● fork返回,开始调度器调度

这个前面提到过,就不多说了

2.写时拷贝

引言:当程序变成二进制后,所有的变量名都会变成地址。
fork之后代码共享,就是子进程被创建时,会以父进程为模板,子进程和父进程默认拥有一份相同的代码和数据,当然页表中存储的地址也是一样的。
在这里插入图片描述
在这里插入图片描述
两个问题:
创建子进程时,为什么不直接把父进程的数据给一份?
因为操作系统按需分配,节省空间。

为什么要拷贝?开新空间就好了啊
这里的写:包括了增删查改,不是全被都被覆盖。可能只修改一部分的数据

上图中页表部分括号里有个只读权限,接下来我们分析一下页表

(i)页表

页表不仅仅有虚拟地址和物理地址,物理地址还包括了权限
在这里插入图片描述
举例:字符常量无法被修改,就是我们在写入时,由虚拟地址到物理地址的转化中,权限中没有写入权限。
写代码时const的意义:把运行时产生的错误提前到编译时(防御性编程)

3.终止进程

进程退出情况

我们写代码时,最后都会return 0,main函数的返回值,就是进程的退出码
一般0表示成功,非0表示失败。
在进程执行结束之后,如果进程失败了,我们最想知道的是他的错误原因

echo $?
这个可以查看进程的退出码

当然错误码我们是无法理解的,所以就有错误码转化为错误描述
strerror()
在这里插入图片描述
我们可以看看linux中的错误码

int main()
{
    for(int i=0;i<200;i++)
    {
        printf("%d: %s\n",i,strerror(i));
    }
    return 0;
}

在这里插入图片描述

函数退出情况

除了进程有退出,函数也是有退出的。
函数也是有返回值的,函数的返回值就是错误码,这个和进程的一样
在这里插入图片描述

总结

总结:
任何进程的最终执行情况我们用两个数字表示==(异常)信号编号+进程退出码

如何让进程退出?
1.main函数return
2.exit(退出码)——终止进程,status(进程退出码)
这个进程退出码status会在进程等待中详细的说

4.进程等待

我们提到的父进程如果不等待子进程,就会使子进程变成僵尸进程,会引发内存泄漏
在这里插入图片描述
所以父进程通过wait的方式去回收子进程的资源,这个是必须要做的事情。
在这里插入图片描述
wait会默认进行阻塞等待,等待任意一个子进程;
返回值大于0,等待成功,等待子进程的pid;返回值小于0,等待失败

int main()
{

    pid_t id = fork();
    if (id == 0)
    {
        // child
        int cnt = 5;
        while (cnt)
        {
            printf("I am child,pid: %d,ppid: %d\n", getpid(), getppid());
            cnt--;
            sleep(1);
        }
        printf("马上变僵尸\n");
        exit(0);
    }
    sleep(10);
    // father
    pid_t rid = wait(NULL);
    if (rid > 0)
    {
        printf("wait success child_id:%d\n", rid);
    }
    return 0;
}

在这里插入图片描述
wait比较简单,我们来看看waitpid()
在这里插入图片描述
status:局部使用的位图形式在这里插入图片描述
在这里插入图片描述
status的8到15位时退出码,0到7时退出信号。

提取status的信号:status&0x7F
这样就把他的前7位的数字取出来了;
提取status的退出码:(status>>8)&0xFF
这样就把他的次低8位的数字取出来了.
当然这种方式太麻烦了,我们有专门的宏来完成这件事
在这里插入图片描述

if (WIFEXITED(status))
    {
        printf("wait success,rid: %d,status: %d,exit code: %d\n",rid,status,WEXITSTATUS(status));
    }

非阻塞等待才是重点
在这里插入图片描述
这里当options设位0,就是阻塞等待,设为WNOHANG就是非阻塞等待。
非阻塞:当在等待子进程退出的时候,父进程还可以去做别的事情

waitpid的返回值:
● 大于0:系统调用成功
● 等于0:系统调用成功,但子进程还没退出
● 小于0:调用失败

我们用代码来看看非阻塞等待的优势

const static int NUM=3;
typedef void(*func_t)();

func_t task[NUM];


void printfNAME()
{
    printf("this is print name\n");
}
void printfNPC()
{
    printf("this is print npc\n");
}
void printfAGE()
{
    printf("this is print age\n");
}

void InitLog()
{
    task[0]=printfNAME;
    task[1]=printfNPC;
    task[2]=printfAGE;
    task[3]=NULL;
}
void Exe()
{
    for(int i=0;task[i];i++)
    {
        task[i]();
    }
}
int main()
{
    InitLog();
    pid_t id = fork();
    if (id == 0)
    {
        // child
        int cnt = 5;
        while (cnt)
        {
            printf("I am child,pid: %d,ppid: %d\n", getpid(), getppid());
            cnt--;
            sleep(1);
        }
        sleep(12);
        exit(111);
    }
    // father
    int status=0;
    pid_t rid = waitpid(id,&status,WNOHANG);
    while(1)
    {
        if(rid>0)
        {
            printf("wait sucess,rid: %d,status: %d,exit code: %d\n",rid,status,WEXITSTATUS(status));
            break;
        }
        else if(rid==0)
        {
            printf("child is running,do other thing\n");
            //开始任务
            printf("$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");
            Exe();
        }
        else
        {
            perror("waitpid");
            break;
        }
        sleep(1);
    }

    return 0;
}

当子进程还在运行的时候,父进程不是傻傻的等,等待的时候可以去完成别的工作。

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

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

相关文章

智能玩具用离线语音识别芯片有什么优势

随着科技的发展&#xff0c;很多智能电子产品和儿童玩具实现了与人类的交互&#xff0c;语音芯片在这些人机交互中起到了不可替代的作用&#xff0c;语音识别芯片在智能玩具中的应用就为其带来了更多的优势。‌ 离线语音识别&#xff0c;即小词汇量、低成本的语音识别系统&…

esp32 wifi 联网后,用http 发送hello 用pc 浏览器查看网页

参考chatgpt Esp32可以配置为http服务器&#xff0c;可以socket编程。为了免除编写针对各种操作系统的app。完全可以用浏览器仿问esp32服务器&#xff0c;获取esp32的各种数据&#xff0c;甚至esp的音频&#xff0c;视频。也可以利用浏览器对esp进行各种操作。但esp不能主动仿…

【深度学习】(2)--PyTorch框架认识

文章目录 PyTorch框架认识1. Tensor张量定义与特性创建方式 2. 下载数据集下载测试展现下载内容 3. 创建DataLoader&#xff08;数据加载器&#xff09;4. 选择处理器5. 神经网络模型构建模型 6. 训练数据训练集数据测试集数据 7. 提高模型学习率 总结 PyTorch框架认识 PyTorc…

【STL】vector 基础,应用与操作

vector 是 C 标准库中最常用的顺序容器之一&#xff0c;提供了动态数组的功能。与普通数组相比&#xff0c;vector 能够根据需求自动扩展或收缩&#xff0c;为程序员提供了更灵活的数据存储方案。本文将详细介绍 vector 的相关操作&#xff0c;并结合实例代码帮助读者深入理解。…

MindShare PCIE 3.0 笔记-第一二章

MindShare 官网&#xff0c;地址如下: MindShare Chapter 1&#xff1a;PCIE 背景介绍 - PCI 总线模型 1. 以 PCI 总线作为外设总线的 SOC 芯片架构 下图展示了一个以 PCI 总线作为外设总线的 SOC 芯片架构(PCI 总线类似 AXI 下的 AHB&#xff1f;)&#xff1a; 由上图可知…

Django Auth组件

文章目录 前言一、使用场景二、使用步骤1.验证用户( authenticate() 方法)2.注册用户3.退出登陆4.装饰器 前言 Django 的用户认证组件基于以下几个核心概念&#xff1a; 1.用户认证&#xff1a;处理用户的登录、注销和密码管理&#xff0c;提供了一个User模型和相关的视图、表…

技术美术一百问(02)

问题 前向渲染和延迟渲染的流程 前向渲染和延迟渲染的区别 G-Buffer是什么 前向渲染和延迟渲染各自擅长的方向总结 GPU pipeline是怎么样的 Tessellation的三个阶段 什么是图形渲染API? 常见的图形渲染API有哪些&#xff1f; 答案 1.前向渲染和延迟渲染的流程 【例图…

图神经网络池化方法

图神经网络池化方法 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 图神经网络池化方法前言一、扁平图池化二、分层图池化1.节点聚类池化2.节点丢弃池化 参考文献 前言 图池化操作根据其池化策略的差异&#xff…

软考(中级-软件设计师)(0919)

软考 一、软件设计师-历年考试考点分布情况-上午-计算机与软件工程知识 知识点分数说明比例软件工程基础知识11开发模型、设计原则、测试方法、质量特性、CMM、Pert图、风险管理14.67%面向对象12面向对象基本概念、面向对象分析与设计、UML、常见算法16.00%数据结构与算法10…

代码随想录算法day37 | 动态规划算法part10 |

今天开始正式子序列系列&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 300.最长递增子序列 本题是比较简单的&#xff0c;感受感受一下子序列题目的思路。 力扣题目链接(opens new window) 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长…

读mamba有感,自然而然产生的问题及答案。

原文链接&#xff1a;https://arxiv.org/abs/2312.00752 Q&#xff1a;为什么说Mamba可以比肩甚至超越transformer&#xff1f;各自有什么优劣&#xff1f; A&#xff1a;Transformer在处理长序列时&#xff0c;存在着计算效率低下的问题&#xff0c;无法对有限窗口之外的任何…

查询中的行选择

用WHERE子句限制从查询返回的行。一个WHERE子句包含一个必须满足的条件&#xff0c;WHERE子句紧跟着FROM子句。如果条件是true&#xff0c;返回满足条件的行。 在语法中&#xff1a; WHERE 限制查询满足条件的行 condition 由列名、表达式、常数和比较操作组成…

bootstrap application nacos环境配置失效

tmd 环境配置 是yaml &#xff0c;yml 后缀配置不生效 (不&#xff0c;看你取得文件名是什么) 如果 file-extension 配置的是yaml 就读取不到 yml 中的配置 2 . 如果还不行&#xff0c;、nacos 配置只能卸载bootstrap.yml 中&#xff0c;application.yml 不生效 bootstrap.yml…

c/c++语言中extern的用法(VS编译)

c/c语言中extern的用法 前言&#xff1a;1. 声明外部变量2. 声明外部函数3. 在头文件中使用注意事项 效果展示&#xff1a; 前言&#xff1a; extern 关键字不仅在 C 语言中使用&#xff0c;在 C 语言中也同样适用。它主要用于声明一个变量或者函数是在别的文件或翻译单元中定…

怎么操作使http变成https访问?

获取SSL证书 选择证书颁发机构&#xff1a;可以选择受信任的免费或付费证书颁发机构&#xff08;CA&#xff09;如JoySSL 申请和验证域名&#xff1a;注册并填写注册码230920&#xff0c;验证域名所有权。下载SSL证书文件到本地电脑. JoySSL品牌证书 注册享大额优惠JoySSL是网…

Android开发高频面试题之——Android篇

Android开发高频面试题之——Android篇 Android开发高频面试题之——Java基础篇 Android开发高频面试题之——Kotlin基础篇 Android开发高频面试题之——Android基础篇 1. Activity启动模式 standard 标准模式,每次都是新建Activity实例。singleTop 栈顶复用。如果要启动的A…

车市状态喜人,国内海外“两开花”

文/王俣祺 导语&#xff1a;随着中秋假期告一段落&#xff0c;“金九”也正式过半&#xff0c;整体上这个销售旺季的数据可以说十分喜人&#xff0c;各家车企不是发布新车、改款车就是推出了一系列购车权益&#xff0c;充分刺激了消费者的购车热情。再加上政府政策的鼎力支持&a…

Unity 使用Editor工具查找 Prefab 中的指定脚本

在 Unity 项目中&#xff0c;随着项目规模的扩大和 Prefab 数量的增加&#xff0c;管理和定位 Prefab 中的脚本变得更加复杂。为了提高开发效率&#xff0c;所以需要编写一个自定义的 Unity Editor 工具&#xff0c;帮助查找某个 Prefab 中是否使用了指定的脚本。本文将介绍如何…

LIN总线CAPL函数——干扰LIN帧响应段(linInvertRespBit )

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

目标检测:滑块验证

最近在做一些爬虫相关的任务&#xff0c;有时候在登录时候需要去做滑块验证&#xff0c;刚好自己是做AI这一块得&#xff0c;就想着使用目标检测去做检测&#xff0c;然后绕过滑块。