嵌入式Linux:创建进程

news2025/1/8 16:04:02

目录

1、fork() 系统调用

1.1、工作机制

1.2、使用场景

2、vfork() 系统调用

2.1、工作机制

2.2、使用场景


在 Linux 系统中,fork()vfork() 是两个常用的系统调用,用于创建新的进程。

1、fork() 系统调用

函数原型如下:

#include <unistd.h>
pid_t fork(void);

返回值:调用 fork() 的进程(父进程)会得到一个返回值。在父进程中,fork() 返回子进程的进程 ID (PID);在子进程中,fork() 返回 0;如果发生错误,则返回 -1,并设置全局变量 errno

1.1、工作机制

fork() 会创建一个新的进程,这个进程被称为子进程。子进程几乎是父进程的完整副本,包括父进程的代码段、数据段、堆栈段和打开的文件描述符。子进程和父进程之间的唯一区别在于它们拥有不同的进程 ID,并且 fork() 的返回值不同。

内存空间:尽管子进程复制了父进程的内存空间,但实际上,现代 Linux 系统使用了“写时复制”(Copy-on-Write, CoW)技术。只有在父进程或子进程试图修改内存中的数据时,内核才会真正为子进程分配新的内存。这种机制极大地提高了 fork() 的效率,避免了不必要的内存复制。

1.2、使用场景

fork() 适用于需要创建子进程来执行与父进程不同任务的场景。它在网络服务器、守护进程和并行处理任务中被广泛应用。例如,网络服务器可以使用 fork() 为每个客户端请求创建一个新的子进程,从而提高系统的并发性。

示例如下:

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

int main() {
    pid_t pid = fork(); // 创建子进程

    if (pid < 0) {
        // fork() 失败
        fprintf(stderr, "fork() 失败\n");
        return 1;
    } else if (pid == 0) {
        // 子进程
        printf("这是子进程, PID: %d\n", getpid());
    } else {
        // 父进程
        printf("这是父进程, 子进程的 PID: %d\n", pid);
    }

    return 0;
}

在这个例子中,fork() 创建了一个新的子进程。父进程和子进程会从 fork() 调用之后的代码开始执行,但它们各自运行在独立的内存空间中。

2、vfork() 系统调用

函数原型如下:

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);

返回值vfork() 的返回值与 fork() 相同。在父进程中,返回子进程的 PID;在子进程中,返回 0;如果出错,则返回 -1 并设置 errno

2.1、工作机制

vfork()fork() 类似,用于创建一个子进程,但它有不同的内存管理机制。vfork() 创建的子进程与父进程共享相同的地址空间,这意味着子进程在调用 exec()_exit() 之前,不会复制父进程的内存空间。这使得 vfork()fork() 更加高效,特别是在子进程很快就要执行新的程序时。

共享地址空间:由于 vfork() 是为了在子进程立即调用 exec()_exit() 的场景下优化的,因此子进程和父进程在 exec()_exit() 之前共享同一内存空间。这意味着如果子进程在此期间修改了共享的内存数据,可能会导致不可预知的后果。

执行顺序vfork() 保证子进程会先运行,直到调用 exec()_exit() 后,父进程才会继续执行。这种行为确保了父进程不会在子进程完成执行之前访问可能被修改的共享内存。

2.2、使用场景

vfork() 适用于子进程需要立即调用 exec() 来执行新程序的场景。例如,在 shell 脚本中执行外部命令时,vfork() 可以提高效率。但由于 vfork() 在某些情况下会带来潜在的安全风险(例如子进程误修改父进程的内存),现代系统通常更推荐使用优化后的 fork()

示例如下:

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

int main() {
    pid_t pid = vfork(); // 创建子进程

    if (pid < 0) {
        // vfork() 失败
        fprintf(stderr, "vfork() 失败\n");
        return 1;
    } else if (pid == 0) {
        // 子进程:立即执行新的程序
        execlp("/bin/ls", "ls", NULL); // 执行 ls 命令
        _exit(0); // 使用 _exit 确保快速退出子进程
    } else {
        // 父进程
        printf("这是父进程\n");
    }

    return 0;
}

在这个例子中,vfork() 创建了一个子进程,并立即使用 execlp() 执行 ls 命令。由于 vfork() 子进程在执行 exec() 之前与父进程共享内存,因此在调用 exec() 之前不能修改父进程的数据,否则可能导致程序行为不确定。

fork()vfork() 的区别总结:

  • 内存管理fork() 通过写时复制为子进程创建独立的内存空间,而 vfork() 让子进程与父进程共享内存空间,直到子进程执行 exec()_exit()
  • 效率vfork()fork() 更高效,特别是在子进程需要立即执行新程序时。但由于现代 Linux 内核的写时复制优化,fork() 的效率也得到了显著提升。
  • 安全性fork() 更加安全可靠,因为它为子进程分配了独立的内存空间。而 vfork() 可能会带来潜在的风险,建议在绝对需要优化性能的情况下使用。

使用建议:

  • 优先使用 fork():由于现代 Linux 系统已经优化了 fork(),在大多数情况下使用 fork() 是更为安全和通用的选择。尤其是在编写复杂的应用程序时,fork() 可以减少不确定性和潜在的错误。
  • 在特定场景下使用 vfork():如果需要创建子进程并立即调用 exec(),可以考虑使用 vfork() 以提高效率。但应确保在调用 exec()_exit() 之前,不会对父进程的内存空间进行任何修改。

理解 fork()vfork() 的工作原理和差异,对于设计和实现高效并发的 Linux 程序至关重要。在不同的应用场景中,根据具体需求选择合适的系统调用,将有助于提高程序的效率和稳定性。

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

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

相关文章

极客说|微软 Phi 系列小模型和多模态小模型

作者&#xff1a;胡平 - 微软云人工智能高级专家 「极客说」 是一档专注 AI 时代开发者分享的专栏&#xff0c;我们邀请来自微软以及技术社区专家&#xff0c;带来最前沿的技术干货与实践经验。在这里&#xff0c;您将看到深度教程、最佳实践和创新解决方案。关注「极客说」&am…

解决 IntelliJ IDEA 中 Tomcat 日志乱码问题的详细指南

目录 前言1. 分析问题原因2. 解决方案 2.1 修改 IntelliJ IDEA 的 JVM 选项2.2 配置 Tomcat 实例的 VM 选项 2.2.1 设置 Tomcat 的 VM 选项2.2.2 添加环境变量 3. 进一步优化 3.1 修改 Tomcat 的 logging.properties3.2 修改操作系统默认编码 3.2.1 Windows 系统3.2.2 Linux …

某小程序sign签名参数逆向分析

文章目录 1. 写在前面2. 接口分析3. 分析还原 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python…

医学图像分析工具02:3D Slicer || 医学影像可视化与分析工具 支持第三方插件

3D Slicer 是一款功能全面的开源医学影像分析软件&#xff0c;广泛应用于影像处理、三维建模、影像配准和手术规划等领域。它支持多种医学影像格式&#xff08;如 DICOM、NIfTI&#xff09;和丰富的插件扩展&#xff0c;是神经科学、放射学和生物医学研究中不可或缺的工具。 在…

Linux系统安装es详细教程

一、下载es及插件 从下面的网址进行对应es版本的下载https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.2-linux-x86_64.tar.gz &#xff0c;想要不同版本的es只需更换对应的版本号即可。 插件下载地址&#xff08;ik分词器、pinyin等&#xff09;es…

电子电气架构 --- 汽车总线基础介绍

我是穿拖鞋的汉子&#xff0c;魔都中坚持长期主义的汽车电子工程师。 老规矩&#xff0c;分享一段喜欢的文字&#xff0c;避免自己成为高知识低文化的工程师&#xff1a; 简单&#xff0c;单纯&#xff0c;喜欢独处&#xff0c;独来独往&#xff0c;不易合同频过着接地气的生活…

安装PyQt5-tools卡在Preparing metadata (pyproject.toml)解决办法

为了在VS code中使用PyQt&#xff0c;在安装PyQt5-tools时总卡在如下这一步 pyqt5 Preparing metadata (pyproject.toml)经过各种尝试&#xff0c;最终问题解决&#xff0c;在此记录方法。 首先进入PyQt5-tools官网查看其适配的Python版本&#xff0c;网址如下&#xff1a; h…

38 Opencv HOG特征检测

文章目录 HOGDescriptor 构造函数setSVMDetector 设置支持向量机&#xff08;SVM&#xff09;检测器&#xff0c;用于目标检测。compute 用于计算图像区域的HOG描述符。detectMultiScale 多尺度检测目标。示例 HOGDescriptor 构造函数 HOGDescriptor(); HOGDescriptor(const S…

分布式搜索引擎之elasticsearch基本使用3

分布式搜索引擎之elasticsearch基本使用3 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&…

人工智能知识分享第九天-机器学习_集成学习

集成学习 概念 集成学习是机器学习中的一种思想&#xff0c;它通过多个模型的组合形成一个精度更高的模型&#xff0c;参与组合的模型称为弱学习器&#xff08;基学习器&#xff09;。训练时&#xff0c;使用训练集依次训练出这些弱学习器&#xff0c;对未知的样本进行预测时…

在线机考|2024华为实习秋招春招编程题(最新)——第3题_个性化歌单推荐系统_300分(十一)

题目内容 假设你是音乐服务的开发者,为了提高用户体验需要解决推荐歌单的同质化问题,保证推荐给用户的所有歌单不包含相同歌曲的。给定一个包含N个歌单和M条歌单重复记录,每个歌单用一个从1到N的整数编号,歌单重复记录包含两个歌单的ID,表示两个歌单有相同的歌曲。 你的任…

学英语学压测:02jmeter组件-测试计划和线程组ramp-up参数的作用

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 Functional Testing功能测试[ˈfʌŋkʃənəl ˈtɛstɪŋ]Sample样…

最新最详细的配置Node.js环境教程

配置Node.js环境 一、前言 &#xff08;一&#xff09;为什么要配置Node.js&#xff1f;&#xff08;二&#xff09;NPM生态是什么&#xff08;三&#xff09;Node和NPM的区别 二、如何配置Node.js环境 第一步、安装环境第二步、安装步骤第三步、验证安装第四步、修改全局模块…

PHP框架+gatewayworker实现在线1对1聊天--接收消息(7)

文章目录 接收消息的原理接收消息JavaScript代码 接收消息的原理 接收消息&#xff0c;就是接受服务器转发的客户端消息。并不需要单独创建函数&#xff0c;因为 ws.onmessage会自动接收消息。我们需要在这个函数里进行处理。因为初始化的时候&#xff0c;已经处理的init类型的…

当算法遇到线性代数(四):奇异值分解(SVD)

SVD分解的理论与应用 线性代数系列相关文章&#xff08;置顶&#xff09; 1.当算法遇到线性代数&#xff08;一&#xff09;&#xff1a;二次型和矩阵正定的意义 2.当算法遇到线性代数&#xff08;二&#xff09;&#xff1a;矩阵特征值的意义 3.当算法遇到线性代数&#xff0…

科研绘图系列:R语言科研绘图之标记热图(heatmap)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理画图系统信息参考介绍 科研绘图系列:R语言科研绘图之标记热图(heatmap) 加载R包 library(tidyverse) library(ggplot2) library(reshape)…

Mysql--基础篇--SQL(DDL,DML,窗口函数,CET,视图,存储过程,触发器等)

SQL&#xff08;Structured Query Language&#xff0c;结构化查询语言&#xff09;是用于管理和操作关系型数据库的标准语言。它允许用户定义、查询、更新和管理数据库中的数据。SQL是一种声明性语言&#xff0c;用户只需要指定想要执行的操作&#xff0c;而不需要详细说明如何…

Excel重新踩坑5:二级下拉列表制作;★数据透视表;

0、在excel中函数公式不仅可以写在单元格里面&#xff0c;还可以写在公式里面。 1、二级下拉列表制作&#xff1a; 2、数据透视表&#xff1a; 概念&#xff1a;通过拖拉就能实现复杂函数才能实现的数据统计问题。 概览&#xff1a;在插入选项中有个数据透视表&#xff0c;数…

Linux-----进程处理(waitpid,进程树,孤儿进程)

目录 waitpid等待 进程树 孤儿进程 waitpid等待 Linux中父进程除了可以启动子进程&#xff0c;还要负责回收子进程的状态。如果子进程结束后父进程没有正常回收&#xff0c;那么子进程就会变成一个僵尸进程——即程序执行完成&#xff0c;但是进程没有完全结束&#xff0c;其…

解决报错net.sf.jsqlparser.statement.select.SelectBody

在我们项目集成mybatis-plus时,总会遇到奇奇怪怪的报错,比如说下面的这个报错 而这个报错,是告诉我们的分页依赖冲突,要加个jsqlparser依赖来解决这个冲突,也相当于平衡,但是可能因为我们版本的不匹配,还是会报错,例如下面这样 但是我们是不知道到底是什么依赖冲突的,这个时候就…