fork函数小解

article/2025/6/23 6:29:47

学了好久终于搞懂fork函数的一些作用

1. fork函数作用:用于创建新的子进程

这是fork最根本的功能,在父进程里创建新的子进程、

但是创建新的子进程之后呢?

子进程和父进程的关系是什么样的?

为什么fork得到的子进程返回值为0,父进程得到的返回值是子进程pid?

以及多级fork函数调用,得到曾曾……曾孙子进程返回的pid是多少呢?

2. 继承父进程的一切

调用fork函数之后,父进程会创建一个几乎一模一样的子进程出来

几乎一模一样是什么意思?

  1. 子进程的代码和父进程完全相同
  2. 子进程的变量以及变量的值和父进程完全相同,包括全局变量,局部变量都相同,但是唯一的不同就是fork()函数的返回值不同,如果用一个变量接受fork函数返回值,那么父子进程这个变量的值就会不同
    1. 比如:父进程执行fork函数创建子进程,这个fork函数在父进程里返回的是子进程的 PID; 在子进程里返回的是 0
    2. 这是为了区分父子,因为他们完全一模一样的话操作系统也不知道谁是爹谁是儿了,就不方便管理,仅此而已
  3. 执行顺序也相同,子进程会接着父进程的执行顺序继续往下执行,也就是接着执行父进程执行fork()创建自己之后的代码,要注意的是如果子进程是在父进程的分支创建,那么子进程也就只能接着这个分支继续执行,也就是说,子进程和父进程执行逻辑一样,不会执行另一个分支,后面我们有题目讲解

再次提醒,fork在父进程的返回值是子进程pid,在子进程中返回0

父子关系判断很简单:这个fork函数谁调用的谁就是爹,被创建的儿子接着fork往下执行

3. 子进程创建新的子进程,子子孙孙无穷匮也?

父进程执行fork创建子进程A,子进程A也执行fork创建孙子进程B

我们知道父进程中执行一个fork返回子进程A的pid,且这个fork在子进程A会返回0

那么子进程A执行另一个fork创建孙子进程B,这个fork在子进程A的返回值是什么呢?

答案如下:

子进程A执行fork()创建孙子进程B,该fork在子进程A中返回孙子进程B的pid

那么聪明的你一定知道该fork在孙子进程B中返回值是0

因为子进程A执行fork函数创建孙子进程B,A是B的父亲,所以在中A返回B的PID,在B中返回0

4. 读如下代码,写出执行结果,并描述父子关系

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
​
int main()
{pid_t pid1, pid2, pid3;pid1 = 0, pid2 = 0, pid3 = 0;pid1 = fork();if (pid1 == 0){pid2 = fork();pid3 = fork();}else{pid3 = fork();if (pid3 == 0){pid2 = fork();}if ((pid1 == 0) && (pid2 == 0)){printf("Level 1\n");}if (pid1 != 0){printf("Level 2\n");}if (pid2 != 0){printf("Level 3\n");}if (pid3 != 0){printf("Level 4\n");}}return 0;
}

分析

  1. 父进程创建子进程1,pid1记录fork()返回值,也就是子进程1的pid,这里用pid1代指子进程1

  2. 父进程继续执行,遇到if-else分支,父进程的pid1保存子进程1的pid,不为0,进入else分支

    1. 父进程再次创建子进程2,pid3保存子进程2的pid

    2. 父进程的pid1和pid3不为0,pid2 = 0,故进入if(pid1!=0)和if(pid3!=0)分支,输出Level 2Level 4父进程结束

  3. 子进程1从pid1 = fork()之后开始执行,pid1 = fork返回值0,且子进程1继承父进程的pid2、pid3,所以子进程进入if分支

    1. 子进程创建孙子进程1,pid2 = 孙子进程1的pid,孙子进程还会创建曾孙子进程1

    2. 创建孙子进程2,pid3 = 孙子进程2的pid

    3. 子进程1结束

    4. 孙子进程1和孙子进程2以及曾孙子进程1都在if分支里,不会到else分支去,故不输出

  4. 子进程2从else 分支的第一个fork函数后开始运行,故pid3 = 0 (fork()返回值),继承父进程的 pid1 = 子进程1的pid,pid2 = 0

    1. 进入if(pid3 ==0)分支,创建孙子进程3,pid2 = 孙子进程3的pid

    2. 子进程2进入if(pid1 != 0) 和if(pid2 != 0)分支,分别输出Level 2和Level 3

    3. 子进程2结束

  5. 孙子进程3的pid2 = 0 (fork返回值),继承子进程2的pid1 = 子进程1的pid,pid3 = 0

    1. 进入if(pid1 != 0)分支,输出Level 2

故答案为:

Level 2
Level 4
Level 2
Level 3
Level 2

执行结果如下:


http://www.hkcw.cn/article/mNgmKImfyo.shtml

相关文章

5月31日day41打卡

简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 → Batch…

配置前端控制器

一、DispatcherServlet 详解 在使用 Spring MVC 框架构建 Web 应用时&#xff0c;DispatcherServlet是整个请求处理流程的核心。本文将深入解析DispatcherServlet的作用、工作原理及其在 Spring MVC 架构中的关键地位。 1.DispatcherServlet 是什么&#xff1f; DispatcherS…

使用PowerBI个人网关定时刷新数据

使用PowerBI个人网关定时刷新数据 PowerBI desktop连接mysql&#xff0c;可以设置定时刷新数据或在PowerBI服务中手动刷新数据,步骤如下&#xff1a; 第一步&#xff1a; 下载网关。以个人网关为例&#xff0c;如图 第二步&#xff1a; 双击网关&#xff0c;点击下一步&…

Dest建筑能耗模拟仿真功能简介

Dest建筑能耗模拟仿真功能简介 全球建筑能耗占终端能源消费的30%以上&#xff0c;掌握建筑能耗模拟是参与绿色建筑认证&#xff08;如LEED、WELL&#xff09;、超低能耗设计、既有建筑节能改造的必备能力。DEST作为国内主流建筑能耗模拟工具&#xff0c;广泛应用于设计院、咨询…

Vue2+Vuex通过数组动态生成store数据(分组模式)

在项目开发中,将数据集中存储在Vuex的store中,能便于数据的统一管理和维护。开发者可以在一个地方对数据进行操作和更新,以避免在组件中分散管理数据带来的混乱和复杂性。 对于状态数据较多情况下,界面操作数据又是数组结构,因业务需求,数组内每个元素都需要单独定义一个…

生成式AI模型学习笔记

文章目录 生成式AI模型1. 定义2. 生成式模型与判别式模型3. 深度生成式模型的类型3.1 能量模型3.2 变分自编码3.2.1 变分自编码器&#xff08;Variational Autoencoder, VAE&#xff09;简介3.2.2 代码示例&#xff08;以 PyTorch 为例&#xff09; 3.3 生成对抗网络3.4 流模型…

DAY 16 numpy数组与shap深入理解

一、NumPy 数组基础笔记 1. 理解数组的维度 &#xff08;Dimensions&#xff09; NumPy 数组的维度 &#xff08;Dimension&#xff09; 或称为 轴 &#xff08;Axis&#xff09; 的概念&#xff0c;与我们日常理解的维度非常相似。 直观判断&#xff1a; 数组的维度层数通常…

Maven 安装与配置指南(适用于 Windows、Linux 和 macOS)

Apache Maven 是一款广泛应用于 Java 项目的项目管理和构建工具。 本文提供在 Windows、Linux 和 macOS 系统上安装与配置 Maven 的详细步骤&#xff0c;旨在帮助开发者快速搭建高效的构建环境。 一、前置条件&#xff1a;安装 Java Development Kit (JDK) Maven 依赖于 Java …

Java对象克隆:从浅到深的奥秘

浅克隆与深克隆在Java中的应用及区别 核心概念 浅克隆 复制对象时仅克隆基本数据类型字段&#xff0c;引用类型字段共享原对象引用。实现方式&#xff1a; class Person implements Cloneable {String name;Address address; // 引用类型字段Overrideprotected Object clone…

【HW系列】—日志介绍

文章目录 一、日志介绍二、Apache日志详解1. 日志存放位置2. 日志类型3. 日志级别4. 常用日志分析命令&#xff08;Linux环境&#xff09; 三、IIS日志详解四、日志分析工具&#xff1a;360星图 一、日志介绍 为什么要使用日志 故障诊断&#xff1a;快速定位系统错误根源安全审…

cuda_fp8.h错误

现象&#xff1a; cuda_fp8.h错误 原因&#xff1a; CUDA Toolkit 小于11.8,会报fp8错误&#xff0c;因此是cuda工具版本太低。通过nvcc --version查看 CUDA Toolkit 是 NVIDIA 提供的一套 用于开发、优化和运行基于 CUDA 的 GPU 加速应用程序的工具集合。它的核心作用是让开发…

内容中台构建数字化管理新路径

数字化内容管理核心架构 现代企业数字化内容管理的核心架构依托于动态元数据架构构建策略与多源数据智能整合体系的双重支撑。通过建立三层架构模型——数据采集层、逻辑处理层与应用服务层&#xff0c;系统能够实现跨平台内容资产的统一索引与语义关联。其中&#xff0c;Bakl…

【连载21】基础智能体的进展与挑战综述-交互风险

20. 智能体外部安全性&#xff1a;交互风险 随着人工智能智能体的发展以及与日益复杂的环境互动&#xff0c;与这些互动相关的安全风险已成为一个关键问题。本章聚焦于人工智能智能体与记忆系统、物理和数字环境及其他智能体的互动。这些互动使人工智能智能体面临各种脆弱性&a…

【Day41】

DAY 41 简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化&#xff1a;调整一个批次的分布&#xff0c;常用与图像数据特征图&#xff1a;只有卷积操作输出的才叫特征图调度器&#xff1a;直接修改基础学习率 卷积操作常见流程如下&#xff1a; 1. 输入 → 卷积层 →…

C++:参数传递方法(Parameter Passing Methods)

目录 1. 值传递&#xff08;Pass by Value&#xff09; 2. 地址传递&#xff08;Pass by Address&#xff09; 3. 引用传递&#xff08;Pass by Reference&#xff09; 数组作为函数参数&#xff08;Array as Parameter&#xff09; 数组作为函数返回值 什么是函数&#xff…

【iOS】方法交换

方法交换 method-swizzling是什么相关API方法交换的风险method-swizzling使用过程中的一次性问题在当前类中进行方法交换类方法的方法交换 方法交换的应用 method-swizzling是什么 method-swizzling的含义是方法交换&#xff0c;他的主要作用是在运行的时候将一个方法的实现替…

GoogLeNet网络模型

GoogLeNet网络模型 诞生背景 在2014年的ImageNet图像识别挑战赛中&#xff0c;一个GoogLeNet的网络架构大放异彩&#xff0c;与VGG不同的是&#xff0c;VGG用的是3*3的卷积&#xff0c;而GoogLeNet从1*1到7*7的卷积核都用&#xff0c;也就是使用不同大小的卷积核组合。 网络…

Linux:动静态库

一&#xff1a;什么是库 库是写好的&#xff0c;现有的&#xff0c;成熟的可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人都从零开始写&#xff0c;因此库的存在一样非同寻常 本质上库是一种可执行代码的二进制形式&#xff0c;可以被操作…

【图像处理入门】2. Python中OpenCV与Matplotlib的图像操作指南

一、环境准备 import cv2 import numpy as np import matplotlib.pyplot as plt# 配置中文字体显示&#xff08;可选&#xff09; plt.rcParams[font.sans-serif] [SimHei] plt.rcParams[axes.unicode_minus] False二、图像的基本操作 1. 图像读取、显示与保存 使用OpenCV…

设计模式——装饰器设计模式(结构型)

摘要 文中主要介绍了装饰器设计模式&#xff0c;它是一种结构型设计模式&#xff0c;可在不改变原有类代码的情况下&#xff0c;动态为对象添加额外功能。文中详细阐述了装饰器模式的角色、结构、实现方式、适合场景以及实战示例等内容&#xff0c;还探讨了其与其他设计模式的…