浅谈 Linux fork 函数

文章目录

  • 前言
  • fork 基本概念
  • 代码演示
    • 示例1:体会 fork 函数返回值的作用
    • 示例2:创建多进程,加深对 fork 函数的理解

前言

本篇介绍 fork 函数。

fork 基本概念

pid_t fork(void)

fork 的英文含义是"分叉",在这里就是 创建子进程。返回值:失败:-1成功,两个返回值:如果当前进程是 父进程,则返回子进程的 id如果当前进程是 子进程,返回 0,返回 0 也表示创建子进程成功可以通过 fork 的返回值判断当前进程是 父进程 还是 子进程。

是的,你没有看错,fork 有两个返回值,这属实有点逆天。

那么 fork 的两个返回值有什么用呢 ?

不着急回答,我们先图解一下 fork:
在这里插入图片描述

左侧是 a 文件中的代码,在 fork 函数前有一堆代码,在 fork 函数后有两行。
在执行 fork() 后,创建了一个子进程(右图),子进程拥有和父进程一样的代码。【其实是不完全一样的,本篇是"浅谈",所以不搞复杂了】

重点来了:

  1. 子进程拥有和父进程一样的代码。
  2. 子进程会和父进程一起执行后续的代码。

如果只想让父进程执行 代码1,子进程执行 代码2,该怎么做呢?
这里 fork 的返回值就派上用场了,fork 的返回值就是用来区分父、子进程,为父、子进程指定不同的业务,具体实现会在"代码演示"中介绍。

代码演示

关于 fork 的概念没什么可说的,直接结合代码,更深入的理解 fork 吧。

示例1:体会 fork 函数返回值的作用

#include <stdio.h>
#include <unistd.h>int main() {int pid ;printf("AAA\n\n");pid = fork();if(pid > 0) {printf("开始执行父进程的代码\n");printf("I'm parent, my id %d .\n", getpid());printf("父进程的代码执行完毕.\n\n");} else if(pid == 0) {printf("开始执行子进程的代码\n");printf("I'm child. my id: %d\n", getpid());printf("子进程的代码执行完毕.\n\n");}printf("BBB.\n");
}

在这里插入图片描述

【非常重要】我们分析以上的输出结果:
① 两个分支都执行了,这证明 fork 返回了两个值,父、子进程会各自进入条件逻辑中执行自己的代码
② “BBB” 被输出了两次,这说明 父、子进程都会执行 fork 函数后面的代码,只有在遇到条件逻辑时,父子进程 才会执行各自的代码。
③ 通过 fork 的返回值,可以区分 父、子进程,从而为 父、子进程 分配不同的业务逻辑。
④ fork 之后 父进程 和 子进程 的执行顺序不确定,这取决于内核所使用的调度算法。【这点没体现出来,但是得知道】

到此,fork 的返回值就解释完了。

我们最后再通过创建多进程来加深对 fork 函数的理解。

示例2:创建多进程,加深对 fork 函数的理解

我们知道,创建进程使用的是 fork 函数,那么创建多进程自然就是循环调用 fork 函数了。

最容易想到的是下面这样:

    for(i=0; i<5; i++) {// 创建 5 个进程pid = fork();if(pid > 0){printf("我是第 %d 个 子进程.\n", i);}}

你仔细想想,这对吗?
我们运行一下:
在这里插入图片描述

原因就是上面提到过的第 ② 句: " 父、子进程都会执行 fork 函数后面的代码,只有在遇到条件逻辑时,父子进程 才会执行各自的代码 "。

也就是说父进程在创建出子进程后,子进程也会继续执行 for 里面的语句,这就会导致子进程继续创建 子子进程,子子进程 也会继续执行 for 里面的语句,然后以此类推,子子进程,再创建 子子子进程 …

要解决这个问题,就是创建出子进程后,让子进程执行完逻辑后就马上退出 for 循环,不要继续创建 子子进程。

正确逻辑如下:

#include <stdio.h>
#include <unistd.h>int main() {int pid, i;for(i=0; i<5; i++) {// 创建 5 个进程pid = fork();if(pid == 0){printf("我是第 %d 个 子进程, pid: %d\n", i, getpid());break;  // 直接让子进程跳出循环}sleep(1);  // 让进程的输出变得有序}return 0;
}

在这里插入图片描述

题外话:
因为当前示例只是为了演示多进程的创建,加深对 fork 函数的理解,所以采用了 break 的方式假装结束子进程的运行,实际上子进程只是跳出 for 循环,子进程还是会继续运行 for 之外后续的语句,但是 for 之外没有后续语句了,子进程就执行完毕,所以这看起来是 break 后子进程就结束了。

实际上结束进程应采用特定的函数,由于本篇只是 “浅谈”,让读者专注于最核心的部分,所以就不扯多了。

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

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

相关文章

Java知识点整理(一)

反射 反射是在运行状态中&#xff0c;动态获取类信息&#xff0c;以及动态调用对象的方法的功能叫做反射机制。在JDBC&#xff0c;Servlet&#xff0c;SpringIOC中 优点&#xff1a;能够灵活的创建代码&#xff0c;动态执行方法访问属性。 缺点&#xff1a;破坏了封装性&…

Mysql学习之MVCC解决读写问题

多版本并发控制 什么是MVCC MVCC &#xff08;Multiversion Concurrency Control&#xff09;多版本并发控制。顾名思义&#xff0c;MVCC是通过数据行的多个版本管理来实现数据库的并发控制。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之&#xff0…

从零自制docker-1-【环境配置 docker go介绍与安装】

文章目录 docker简介举例docker安装go语言go安装go 配置 docker简介 Docker可以看作是一种极其轻巧的“虚拟机”&#xff0c;它允许你将一个或多个程序及其运行环境打包在一起&#xff0c;形成一个标准化的单元&#xff0c;这个单元可以在任何支持Docker的系统上运行&#xff…

神经网络之万能定理python-pytorch实现,可以拟合任意曲线

神经网络之万能定理python-pytorch实现&#xff0c;可以拟合任意曲线 博主&#xff0c;这几天一直在做这个曲线拟合的实验&#xff0c;讲道理&#xff0c;网上可能也有很多这方面的资料&#xff0c;但是博主其实试了很多&#xff0c;效果只能对一般的曲线还行&#xff0c;稍微…

114.龙芯2k1000-pmon(13)- 串口如何用

本文是讲原理图的部分&#xff0c;跟pmon的关系不大&#xff01;&#xff01; 参考手册&#xff1a;《龙芯2K1000处理器用户手册.pdf》 刚刚看数据手册&#xff0c;让我是有点惊讶&#xff0c;但是也让我迷惑。&#xff08;一个串口复用为4个是啥意思&#xff1f;&#xff09;…

MogaNet实战:使用MogaNet实现图像分类任务(一)

文章目录 摘要安装包安装timm 数据增强Cutout和MixupEMA项目结构计算mean和std生成数据集 摘要 论文&#xff1a;https://arxiv.org/pdf/2211.03295.pdf 作者多阶博弈论交互这一全新视角探索了现代卷积神经网络的表示能力。这种交互反映了不同尺度上下文中变量间的相互作用效…

#WEB前端(DIV、SPAN)

1.实验&#xff1a;DIV、SPAN 2.IDE&#xff1a;VSCODE 3.记录&#xff1a; 类? 4.代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdev…

Python3零基础教程之数学运算专题进阶

大家好,我是千与编程,今天已经进入我们Python3的零基础教程的第十节之数学运算专题进阶。上一次的数学运算中我们介绍了简单的基础四则运算,加减乘除运算。当涉及到数学运算的 Python 3 刷题使用时,进阶课程包含了许多重要的概念和技巧。下面是一个简单的教程,涵盖了一些常…

BUUCTF---数据包中的线索1

1.题目描述 2.下载附件&#xff0c;是一个.pcap文件 3.放在wireshark中&#xff0c;仔细观察数据流&#xff0c;会发现有个叫fenxi.php的数据流 4.这条数据流是http,且使用GET方式&#xff0c;接下来我们使用http.request,methodGET 命令来过滤数据流 5.在分析栏中我们追踪htt…

VirtualBox 桥接网卡 未指定 “未能启动虚拟电脑Ubuntu,由于下述物理网卡未找到:”

解决办法&#xff0c;安装虚拟网卡&#xff0c;win11查找方式&#xff1a;控制面板→网络和共享中心→更改适配器设置 此时出现下面情况就算安装成功 但是如果报错&#xff1a;找不到指定的模块 则按下面步骤删除干净垃圾重新上面操作 先安装CCleaner, 链接:CCleaner Makes Y…

Day10:基础入门-HTTP数据包Postman构造请求方法请求头修改状态码判断

目录 数据-方法&头部&状态码 案例-文件探针 案例-登录爆破 工具-Postman自构造使用 思维导图 章节知识点&#xff1a; 应用架构&#xff1a;Web/APP/云应用/三方服务/负载均衡等 安全产品&#xff1a;CDN/WAF/IDS/IPS/蜜罐/防火墙/杀毒等 渗透命令&#xff1a;文件…

51单片机-(定时/计数器)

51单片机-&#xff08;定时/计数器&#xff09; 了解CPU时序、特殊功能寄存器和定时/计数器工作原理&#xff0c;以定时器0实现每次间隔一秒亮灯一秒的实验为例理解定时/计数器的编程实现。 1.CPU时序 1.1.四个周期 振荡周期&#xff1a;为单片机提供定时信号的振荡源的周期…

k8s.gcr.io/pause:3.2镜像丢失解决

文章目录 前言错误信息临时解决推荐解决onetwo 前言 使用Kubernetes&#xff08;k8s&#xff09;时遇到了镜像拉取的问题&#xff0c;导致Pod沙盒创建失败。错误显示在尝试从k8s.gcr.io拉取pause:3.2镜像时遇到了超时问题&#xff0c;这通常是因为网络问题或者镜像仓库服务器的…

springcloud:3.3测试重试机制

服务提供者【test-provider8001】 Openfeign远程调用服务提供者搭建 文章地址http://t.csdnimg.cn/06iz8 相关接口 测试远程调用&#xff1a;http://localhost:8001/payment/index 服务消费者【test-consumer-resilience4j8004】 Openfeign远程调用消费者搭建 文章地址http:/…

守护无价数据:文件备份的重要性与实用方案

一、数据安全之盾&#xff1a;文件备份的必要性 在数字化时代&#xff0c;我们生活的各个方面都与电子文件紧密相连。从工作文档、个人照片到珍贵视频&#xff0c;这些文件记录着我们的成长、工作与生活。然而&#xff0c;随着电子设备的使用频率增加&#xff0c;数据丢失的风…

mTSL: netty单向/双向TLS连接

创建证书 不管是单向tls还是双向tls(mTLS)&#xff0c;都需要创建证书。 创建证书可以使用openssl或者keytool&#xff0c;openssl 参考 mTLS: openssl创建CA证书 单向/双向tls需要使用到的相关文件: 文件单向tls双向tlsServer端Client端备注ca.key----需要保管好&#xff0…

Visual Studio C++项目远程断点调试客户现场程序方法

前言 程序开发一个很常见的场景&#xff0c;就是程序在自己本地部署调试明明一点问题都没有&#xff0c;但是部署到客户现场就问题百出&#xff0c;要调试起来还很困难&#xff0c;在自己本地也没有条件复现&#xff0c;很多时候只能靠日志一点点排查和猜测&#xff0c;耗费大…

[设计模式Java实现附plantuml源码~行为型] 对象状态及其转换——状态模式

前言&#xff1a; 为什么之前写过Golang 版的设计模式&#xff0c;还在重新写Java 版&#xff1f; 答&#xff1a;因为对于我而言&#xff0c;当然也希望对正在学习的大伙有帮助。Java作为一门纯面向对象的语言&#xff0c;更适合用于学习设计模式。 为什么类图要附上uml 因为很…

SparkStreaming在实时处理的两个场景示例

简介 Spark Streaming是Apache Spark生态系统中的一个组件&#xff0c;用于实时流式数据处理。它提供了类似于Spark的API&#xff0c;使开发者可以使用相似的编程模型来处理实时数据流。 Spark Streaming的工作原理是将连续的数据流划分成小的批次&#xff0c;并将每个批次作…

(C语言)函数详解上

&#xff08;C语言&#xff09;函数详解上 目录&#xff1a; 1. 函数的概念 2. 库函数 2.1 标准库和头文件 2.2 库函数的使用方法 2.2.1 sqrt 功能 2.2.2 头文件包含 2.2.3 实践 2.2.4 库函数文档的一般格式 3. 自定义函数 3.1 函数的语法形式 3.2 函数的举例 4. 形参和实参 4.…