《Linux系统编程篇》fork函数——基础篇

文章目录

  • 引言
  • fork() 函数概述
    • 父子进程
  • fork函数
    • fork() 的常见问题
    • fork() 的优势与限制
  • 结论

命为志存。 —— 朱熹

引言

《Linux系统编程篇》——基础篇首页传送门

本节我们正式进入Linux的进程代码编写。

fork() 是 Unix 系统中一个重要的系统调用,用于创建一个新的进程。它是创建进程的核心函数之一,其特性和用法在进程管理中至关重要。本文将带你深入了解 fork() 函数的使用、返回值、常见问题及其在操作系统中的重要性。

fork() 函数概述

在 Linux 中,所有的进程都是通过 fork() 派生而来。当一个进程调用 fork() 时,操作系统会复制当前进程的上下文,为它创建一个几乎完全相同的副本,这个副本被称为子进程,而原始进程被称为父进程。

这也是人们口中的父子进程的概念

父子进程

进程a->fork->进程b

  • 我们称作进程a进程b的父进程,反之进程b则是进程a的子进程

fork函数

我们在命令终端,可以轻易的使用man手册来看,这个函数的作用返回值等,以及这个函数所需要的头文件是什么。

man 2 fork

fork() 是一个在Unix系统中可用的系统调用函数,用于创建一个新的进程。

fork() 函数的原型如下:

#include <unistd.h>

pid_t fork(void);

fork() 函数在调用时会复制当前进程创建一个新的子进程。子进程将几乎完全复制父进程的状态,包括代码、数据、打开的文件等。父进程和子进程之间的唯一区别是进程 ID(PID)和返回值。

  • 如果 fork() 返回 -1,则表示创建子进程失败。
  • 如果 fork() 返回 0,则表示当前代码运行在子进程中。
  • 如果 fork() 返回一个正整数,表示当前代码运行在父进程中,并且返回的值是子进程的PID

好,接着我们写一段调用fork函数的一个小demo

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

int main()
{
        pid_t pid;
        
        pid = fork();

        printf("pid = %d\n",pid);
        return 0;
}

在这里插入图片描述

编译运行后可以看到我的pid被打印了两次,也就是说我的printf函数被执行了两次。

结合我们提前整理的资料来看,使用fork之后返回的pid,一个是3403,一个是0,那么输出是0的这个应该是子进程打印的,那么另一个则是我的父进程打印的,这一区别使父子进程能够在相同的代码段内执行不同的操作。

例如,父进程可以根据 fork() 的返回值来监控子进程的运行状态,而子进程则可以独立执行任务。

我们升级这个程序继续观察一下。

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

int main()
{
	pid_t pid;
       
	printf("*********  test log 01 **********\n");

    pid = fork();
	printf("pid = %d\n",pid);
	
	if(pid == 0){
		printf("this is child\n");
		while(1){usleep(500);}
	}else{
		printf("this is father\n");
		while(1){usleep(500);}
	}


	return 0;
}

在这里插入图片描述
代码解释:
fork() 被调用时,系统会创建一个新进程。
代码中,pidfork() 的返回值,如果 pid == 0 表示这是子进程,否则就是父进程。
父进程可以通过 wait() 函数等待子进程执行完成。

这次在fork之前加了打印,可见在调用fork之前,我们的代码还是单进程再跑的。在fork之后也做了相关的判断,看到这里我想大家应该掌握了进程的奥秘了。

于是我们总结一下,写一个进程小框架,方便日后便捷使用。

#include <stdio.h>
#include <unistd.h>

int main() {
    pid_t pid = fork();

    if (pid == -1) {
        // 创建子进程失败
        perror("fork failed");
    } else if (pid == 0) {
        // 子进程代码
        printf("Hello from child process!\n");
    } else {
        // 父进程代码
        printf("Hello from parent process!\n");
        printf("Child process ID: %d\n", pid);
    }

    return 0;
}

到了这里恭喜你,学会了进程,剩下的一些骚操作就是在此基础上不断的扩展延伸,以及迭代。
但是请注意
当一个进程调用fork()创建一个子进程时,子进程会复制父进程的内存空间,包括代码段、数据段、堆和栈等。这意味着在刚刚创建时,父进程和子进程的内存是一样的,但在后续的运行过程中,它们的内存是相互独立的。

现代操作系统中为了提高效率,通常使用写时复制(Copy-On-Write,COW )技术。

写时复制(Copy-On-Write,COW )
这意味着在 fork() 后,父子进程共享相同的内存页,直到其中一个进程试图修改这些页时,操作系统才会真正复制这些页。这样可以显著减少内存的占用,优化性能。

fork() 的常见问题

  • 僵尸进程(Zombie Process):如果父进程在子进程结束后未调用 wait() 或 waitpid() 函数读取子进程的状态信息,子进程将成为僵尸进程。这会占用系统资源,导致系统无法创建新的进程。
  • 多次 fork():如果不慎多次调用 fork(),可能会产生大量子进程,消耗系统资源,甚至造成“fork 炸弹”(即创建太多进程导致系统资源耗尽,系统崩溃)。
  • COW 效率:尽管写时复制提高了效率,但在高负载情况下,COW 的性能可能会受限。

Copy-On-Write(COW)是一种内存管理技术,通常用于优化进程之间的内存共享和复制操作。在 COW 机制中,当多个进程共享同一块内存时,只有在其中一个进程尝试修改这块内存时,系统才会执行复制操作,确保每个进程都能看到自己的独立副本,从而实现了延迟复制的效果。
COW 的效率主要体现在以下几个方面:

  1. 节省内存开销:COW 允许多个进程共享同一块内存,避免了不必要的内存复制。只有在必要的时候才会进行复制,从而节省内存开销。
  2. 减少复制时间:由于只有在写入操作时才会执行复制,因此在大多数情况下,COW 可以减少复制所需的时间,提高了操作的效率。
  3. 提高性能:通过延迟复制操作,COW 可以提高程序的性能,特别是在需要频繁复制内存数据的情况下,避免了不必要的复制开销。

fork() 的优势与限制

  • 优势:fork() 是创建子进程的简单方式,适合多任务并行处理的应用场景。写时复制机制降低了资源消耗,提升了系统效率。
  • 限制:在资源受限的嵌入式系统或实时系统中,频繁使用 fork() 可能导致性能下降。此外,不恰当的 fork() 使用可能引发僵尸进程或系统资源耗尽等问题。

结论

fork() 是 Linux 系统中关键的系统调用,理解它的行为和特性是掌握 Linux 进程管理的关键一步。掌握 fork() 的用法和注意事项,可以帮助开发者设计出高效、健壮的多进程应用。在实际开发中,fork() 通常与 execwait 等函数配合使用,以满足多任务系统的要求。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于KU115+ZU19EG+C6678 的高性能6U VPX 载板

基于KU115ZU19EGC6678 的高性能6U VPX 载板&#xff0c;板载 2 个 HPC 形式的FMC 连接器&#xff08;用于外部信号扩展&#xff09;。板卡选用了 1 片Xilinx 公司的Kintex UltraScale 系列 FPGA 家族中的XCKU115-2FLVA1517I 和 1 片 Zynq UltraScale MPSoC 家族的XCZU19EG-2FFV…

USB Type-C 受电端取电快充协议芯片,支持PD+QC+FCP+SCP+AFC快充协议

前言 随着科技的飞速发展&#xff0c;电子设备对于快速充电的需求日益增加。为了满足这一需求&#xff0c;市场上涌现出了众多快充技术和产品。其中&#xff0c;XSP08Q诱骗取电芯片以其卓越的性能和广泛的应用场景&#xff0c;成为了快充领域的一颗璀璨明星。本文将对XSP08Q P…

Flutter Row组件实战案例

In this section, we’ll continue our exploration by combining the Row and Container widgets to create more complex layouts. Let’s dive in! 在本节中&#xff0c;我们将继续探索&#xff0c;结合“Row”和“Container”小部件来创建更复杂的布局。让我们开始吧! Sc…

CMake 生成器表达式介绍

【写在前面】 生成器表达式在构建系统生成期间进行评估&#xff0c;以生成特定于每个构建配置的信息。它们的形式为 $<...>。例如&#xff1a; target_include_directories(tgt PRIVATE /opt/include/$<CXX_COMPILER_ID>) 这将扩展为 “/opt/include/GNU”、“/opt…

李宇皓现身第十届“文荣奖”,allblack造型帅气绅士引关注

近日&#xff0c;第十届“文荣奖”在众人的期待中拉开帷幕&#xff0c;与众多影视奖项不同&#xff0c;“文荣奖”始终关注年轻群体需求&#xff0c;致力于发掘和扶植影视新人新作&#xff0c;为热爱影视行业的新人提供宝贵机会与激励。今年的文荣奖评委阵容十分强大&#xff0…

深度学习:SGD的缺点

首先看下述函数&#xff1a; 最小值为x0&#xff0c;y0处 先了解下它的梯度特征。了理解其梯度特征&#xff0c;我们需要计算其梯度向量。 梯度向量 ∇f 是函数 f 在每个变量方向上的偏导数组成的向量。具体来说&#xff1a; ∇f(∂f/∂x,∂f∂/y) 首先&#xff0c;我们计算 f …

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…

如何用猿大师办公助手实现OA系统中Word公文/合同在线编辑及流转?

在OA系统或者合同管理系统中&#xff0c;我们会经常遇到网页在线编辑Word文档形式的公文及合同的情况&#xff0c;并且需要上级对下级的公文进行批注等操作&#xff0c;或者不同部门的人需要签字审核&#xff0c;这就需要用到文档流转功能&#xff0c;如何用猿大师办公助手实现…

3DS MAX三维建模平面基础与修改工具(图形编辑与二维建模修改工具)

又是一年1024祝大家程序员节日快乐 3DS MAX三维建模平面基础与修改工具&#xff08;图形编辑与二维建模修改工具&#xff09; 欢迎大家来学习3DS MAX教程&#xff0c;在这里先说一下研究好3ds Max一定要一边看教程一边要自己学的操作才能更快的进步&#xff0c;预祝大家学习顺利…

医疗保健知识中台:引领医疗行业智能化转型的新篇章

前言 随着科技的迅猛进步&#xff0c;医疗保健领域正迎来一场深刻的智能化变革。在这场变革中&#xff0c;知识中台作为医疗行业智能化升级的重要基石&#xff0c;正逐步成为提升医疗服务质量和效率的关键驱动力。本文将深入剖析医疗保健知识中台的内容构成、应用场景以及更新…

控制回撤哪家强?魔改DMA指标,比MACD更强大!

一、DMA的基本原理 前边我们讲过MACD&#xff0c;它利用了短期EMA和长期EMA的偏离来做文章&#xff0c;今天要讲的DMA也是类似的思路。DMA和MACD的本质区别在于&#xff0c;它在计算均线时将EMA替换为了SMA&#xff0c;其他的两者基本一致。 其完整的计算公式如下。很明显&am…

C++设计模式创建型模式———简单工厂模式、工厂方法模式、抽象工厂模式

文章目录 一、引言二、简单工厂模式三、工厂方法模式三、抽象工厂模式四、总结 一、引言 创建一个类对象的传统方式是使用关键字new &#xff0c; 因为用 new 创建的类对象是一个堆对象&#xff0c;可以实现多态。工厂模式通过把创建对象的代码包装起来&#xff0c;实现创建对…

生成式 AI 与向量搜索如何扩大零售运营:巨大潜力尚待挖掘

在竞争日益激烈的零售领域&#xff0c;行业领导者始终在探索革新客户体验和优化运营的新途径&#xff0c;而生成式 AI 和向量搜索在这方面将大有可为。从个性化营销到高效库存管理&#xff0c;二者在零售领域的诸多应用场景中都展现出变革性潜力&#xff0c;已成为保持行业领先…

leetcode438. 找到字符串中所有字母异位词

题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 示例 1: 输入: s "cbaebabacd", p "abc" 输出: [0,6] 解释: 起始索引等于 0 的子串是 &quo…

【IC每日一题】

IC每日一题 1 组合逻辑VS时序逻辑1.1 组合逻辑1.1.1 竞争冒险1.1.2 解决方法 1.2 时序逻辑1.3 比较1.4 场景 2 计数器2.1 代码片段法2.2 实现计数器--异步复位&#xff0c;带clear端&#xff0c;计10则归0&#xff1b; 1 组合逻辑VS时序逻辑 1.1 组合逻辑 组合逻辑&#xff1…

MySQL练习题-求连续、累计、环比和同比问题

目录 准备数据 1&#xff09;求不同产品每个月截止当月最近3个月的平均销售额 2&#xff09;求不同产品截止当月的累计销售额 3&#xff09;求环比增长率和同比增长率 准备数据 -- product 表示产品名称&#xff0c;ym 表示年月&#xff0c;amount 表示销售金额&#xff…

【K8S系列】Kubernetes Service 基础知识 详细介绍

在 Kubernetes 中&#xff0c;Service 是一种抽象的资源&#xff0c;用于定义一组 Pod 的访问策略。它为这些 Pod 提供了一个稳定的访问入口&#xff0c;解决了 Pod 可能频繁变化的问题。本文将详细介绍 Kubernetes Service 的类型、功能、使用场景、DNS 和负载均衡等方面。 1.…

react 总结+复习+应用加深

文章目录 一、React生命周期1. 挂载阶段&#xff08;Mounting&#xff09;补充2. 更新阶段&#xff08;Updating&#xff09;补充 static getDerivedStateFromProps 更新阶段应用补充 getSnapshotBeforeUpdate3. 卸载阶段&#xff08;Unmounting&#xff09; 二、React组件间的…

windows 训练yolov8官方数据集

第一步&#xff1a;安装Anaconda3-2024.06-1-Windows-x86_64.exe 下载地址&#xff1a;https://repo.anaconda.com/archive/ 第二步&#xff1a;创建环境 打开Anaconda Prompt 输入 conda info -e 打印&#xff1a; 已经安装了一些环境&#xff0c;然后我们创建新的环境&a…

大模型面试挺水的,面试官听到这些直接过

AI大模型600道面试总结(LLM) 1、目前主流的开源模型体系有哪些? 目前 主流的开源模型体系 分三种: 第一种:prefixDecoder系 介绍:输入双向注意力&#xff0c;输出单向注意力 代表模型:ChatGLM、ChaGLM2、U-PaLM 第二种:causal Decader系 介绍:从左到右的单向注意力 代表…