嵌入式Linux系统编程 — 7.4 fork、vfork函数创建子进程

目录

1 父进程与子进程概念

2 fork创建子进程

3  系统调用 vfork()函数

4 vfork与 fork函数如何选择


1 父进程与子进程概念

进程与子进程是操作系统中的一个基本概念,用于描述进程之间的层级关系。下面是对这一概念的简要说明:

  • 父进程:在操作系统中,创建新进程的现有进程被称为父进程。父进程可以生成一个或多个子进程,并且通常在子进程执行期间继续运行。

  • 子进程:由父进程创建的进程称为子进程。子进程可以是父进程的一个副本,继承父进程的某些资源和属性,也可以是完全不同的进程,执行不同的任务。

父进程与子进程有如下的关系:

  • 父子关系:子进程通常继承父进程的资源,如文件描述符、环境变量等,但它们拥有自己的地址空间和代码执行路径。父进程和子进程可以通过进程间通信(IPC)机制进行数据交换,如管道、消息队列、共享内存等。

  • 生命周期:子进程的生命周期可以独立于父进程,即使父进程结束,子进程也可以继续运行,如果父进程没有等待子进程就终止了,子进程会变成“僵尸进程”,直到被操作系统回收。

2 fork创建子进程

在诸多的应用中,创建多个进程是任务分解时行之有效的方法,譬如,某一网络服务器进程可在监听客户端请求的同时,为处理每一个请求事件而创建一个新的子进程,与此同时,服务器进程会继续监听更多的客户端连接请求。在一个大型的应用程序任务中,创建子进程通常会简化应用程序的设计,同时提高了系统的并发性。

一个现有的进程可以调用 fork()函数创建一个新的进程, 调用 fork()函数的进程称为父进程,由 fork()函数创建出来的进程被称为子进程 , fork()函数原型如下所示:

#include <unistd.h>pid_t fork(void);
  • 返回值fork() 调用在父进程中返回子进程的 PID,在子进程中返回 0。

下面是 fork() 函数的示例程序,使用它来创建一个新的进程: 

#include <stdio.h>
#include <unistd.h> // 包含fork函数的头文件int main() 
{int pid = fork(); // 创建新进程if (pid < 0) {// fork失败fprintf(stderr, "Fork failed");return 1;} else if (pid == 0) {// 这是子进程printf("This is the child process. PID: %d\n", getpid());} else {// 这是父进程printf("This is the parent process. PID: %d, Child PID: %d\n", getpid(), pid);}// 父进程和子进程都可以继续执行以下代码printf("Parent and child continue to execute...\n");return 0;
}

fork() 调用会返回两次:一次在父进程中,返回子进程的PID;一次在子进程中,返回0。如果 fork() 调用失败,它会在父进程中返回一个负值。

3  系统调用 vfork()函数

vfork()是Linux系统中的一个系统调用,用于创建一个新的进程。与 fork() 函数不同,vfork() 创建的子进程会立即暂停,直到父进程调用 exec() 系列函数或者子进程退出。这种特性使得 vfork() 适合于那些创建子进程后立即调用 exec() 替换子进程映像的场景,因为它避免了父进程和子进程之间的上下文切换。vfork()函数原型如下所示:

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

下面是一个使用 vfork() 的简单示例程序:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main() 
{pid_t pid = vfork(); // 创建新进程if (pid < 0) {// vfork失败perror("vfork failed");exit(EXIT_FAILURE);} else if (pid == 0) {// 这是子进程,应该尽快调用exec()系列函数// 这里使用execl()作为示例execl("/bin/ls", "ls", "-l", NULL);// 如果execl调用失败,输出错误信息并退出perror("execl failed");_exit(EXIT_FAILURE);} else {// 这是父进程printf("This is the parent process. PID: %d, Child PID: %d\n", getpid(), pid);}// 父进程的其他代码可以继续执行return 0;
}

如果 vfork() 成功,它会返回子进程的PID给父进程,返回0给子进程。如果调用失败,它会返回-1给父进程,并设置 errno 以指示错误。程序的运行结果如下:

  1. 父进程的进程ID(PID)是 5321。
  2. 子进程的进程ID(PID)是 5322。
  3. 子进程执行了 ls -l 命令,列出了当前目录下的文件和目录。

4 vfork与 fork函数如何选择

vfork()与 fork()函数主要有以下两个区别:

  • vfork()与 fork()一样都创建了子进程,但 vfork()函数并不会将父进程的地址空间完全复制到子进程中,因为子进程会立即调用 exec(或_exit) ,于是也就不会引用该地址空间的数据。不过在子进程调用 exec 或_exit 之前,它在父进程的空间中运行、 子进程共享父进程的内存。这种优化工作方式的实现提高的效率; 但如果子进程修改了父进程的数据、进行了函数调用、或者没有调用 exec 或_exit 就返回将可能带来未知的结果。
  • 另一个区别在于, vfork()保证子进程先运行, 子进程调用 exec 之后父进程才可能被调度运行。

虽然 vfork()系统调用在效率上要优于 fork(),但是 vfork()可能会导致一些难以察觉的程序 bug,所以尽量避免使用 vfork()来创建子进程,虽然 fork()在效率上并没有 vfork()高,但是现代的 Linux 系统内核已经采用了写时复制技术来实现 fork(),其效率较之于早期的 fork()实现要高出许多,除非速度绝对重要的场合,我们的程序当中应舍弃 vfork()而使用 fork()。
 

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

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

相关文章

从项目中初识Autosar状态机转换

目录 0 前言 1 状态转换 1.1 BSM TO RMS 1.2 RMS TO RSS 1.3 RMS TO NOS 1.4 RSS TO PBSM 1.5 PBSM TO BSM 1.6 RSS TO NOS 1.7 RSS TO RMS 2 结尾 0 前言 之前在这篇《从项目中初识Autosar网络管理》已经和大家讲了Autosar网络管理的几个状态机以及定时器的大致概念&a…

【网安播报】CocoaPods 曝关键漏洞,应用程序面临供应链攻击风险

1、CocoaPods 曝关键漏洞&#xff0c;数百万 macOS 和 iOS 应用程序面临供应链攻击风险 开源依赖管理器 CocoaPods 中的安全漏洞暴露了数千个软件包&#xff0c;利用这些漏洞的攻击者可以将恶意代码注入合法应用&#xff0c;通过受信任的渠道分发恶意软件&#xff0c;并破坏用户…

Qt QWizard新建向导实例

使用QWizard做新建向导&#xff0c;最简单的实例 class MyWizard : public QWizard { public: MyWizard(QWidget* parent nullptr); QWizardPage* createFirstPage(); QWizardPage* createSecondPage(); QWizardPage* createThirdPage(); }; MyWizard::MyWizard(QWidget* par…

最近点对问题(算法与数据结构设计)

课题内容和要求 最近点对问题&#xff0c;在二维平面上输入n个点列P。其中任一点pi&#xff08;xi&#xff0c;yi&#xff09;&#xff0c;编写程序求出最近的两个点。使用穷举法实现&#xff0c;算法复杂度O(n2)&#xff1b;优化算法&#xff0c;以O(nlog2n)实现这一问题 数…

静脉分割YOLOV8-SEG

静脉分割&#xff0c;YOLOV8*SEG资源-CSDN文库 首先使用YOLOV8-SEG训练&#xff0c;得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;从而摆脱PYTORCH依赖&#xff0c;支持C,PYTHON,ANDROID调用

Java信号量semaphore的原理与使用方法

Semaphore的基本概念 在Java中&#xff0c;Semaphore是位于java.util.concurrent包下的一个类。它的核心就是维护了一个许可集。简单来说&#xff0c;就是有一定数量的许可&#xff0c;线程需要先获取到许可&#xff0c;才能执行&#xff0c;执行完毕后再释放许可。 那么&…

尚品汇-(十五)

&#xff08;1&#xff09;快速入门 SpringBoot形式创建 Maven形式创建&#xff1a; 加入依赖&#xff1a; 创建启动类&#xff1a; 设置头文件 就想Jsp的<%Page %>一样 &#xff0c;Thymeleaf的也要引入标签规范。不加这个虽然不影响程序运行&#xff0c;但是你的idea…

顶会FAST24最佳论文|阿里云块存储架构演进的得与失-4.EBS不同架构性能提升思路

3.1 平均延迟与长尾延迟 虚拟磁盘&#xff08;VD&#xff09;的延迟是由其底层架构决定的&#xff0c;具体而言&#xff0c;取决于请求所经历的路径。以EBS2为例&#xff0c;VD的延迟受制于两跳网络&#xff08;从BlockClient到BlockServer&#xff0c;再至ChunkServer&#x…

Xilinx FPGA:vivado关于IIC的一些零碎知识点

一、简介 IlC(inter-Integrated circuit)总线是一种由NXP(原PHILIPS)公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场合使用&#xff0c;传输距离短&#xff0c;任意时刻只能有一个主机等特性…

13 协程设计原理与汇编实现

协程的问题 为什么要有协程?协程的原语操作?协程的切换?协程的struct如何定义?协程的scheduler(调度)如何定义?调度策略如何实现?协程如何与posix,api兼容?协程多核模式?协程的性能如何测试?为什么要有协程 同步的编程方式,异步的性能。同步编程时,我们需要等待io就…

信息技术课堂纪律管理:从混乱到秩序的智慧转型

引言&#xff1a; 在信息爆炸的时代&#xff0c;信息技术课程如同一把开启未来世界大门的钥匙&#xff0c;为学生们搭建起探索科技奥秘的桥梁。然而&#xff0c;面对着屏幕背后的无限诱惑&#xff0c;维持课堂纪律&#xff0c;确保学生们专注于学习&#xff0c;成为了每位信息…

C/C++内存分布

1.内存分布简略图 2.全局变量和静态变量的区别 (1)局部静态变量&#xff1a;存储在数据段中&#xff0c;局部静态变量的作用域在当前函数中&#xff0c;出了函数就不能使用该变量&#xff0c;但局部静态变量的生命周期是在整个程序间&#xff0c;局部静态变量要运行到这一行才…

【Java14】构造器

Java中的构造器在创建对象&#xff08;实例&#xff09;的时候执行初始化。Java类必须包含一个或一个以上的构造器。 Java中的构造器类似C中的构造函数。 Java中对象&#xff08;object&#xff09;的默认初始化规则是&#xff1a; 数值型变量初始化为0&#xff1b;布尔型变量…

【CSAPP】-cachelab实验

目录 实验目的与要求 实验设备与软件环境 实验过程与结果&#xff08;可贴图&#xff09; 操作异常问题与解决方案 实验总结 实验目的与要求 1、掌握应用程序性能的优化方法&#xff1b; 2、理解存储器层次结构在程序运行过程中所起的重要作用&#xff1b; 3、让学生更好…

高考志愿填报的六个不要

在高考志愿填报这个关键时刻&#xff0c;确实需要谨慎行事&#xff0c;避免一些常见的错误。以下是高考志愿填报的六个“不要”&#xff0c;希望能为你提供一些有用的建议&#xff1a; 1、不要盲目跟风 每个人的兴趣、能力和未来规划都不同&#xff0c;不要仅仅因为某个专业或…

Gradle基础:从入门到掌握

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 在现代软件开发中&#xff0c;自动化构建工具是提高效率和管理依赖的重要手段。而Gradle作为一种灵活且强大的构…

python基础篇(9):模块

1 模块简介 Python 模块(Module)&#xff0c;是一个 Python 文件&#xff0c;以 .py 结尾. 模块能定义函数&#xff0c;类和变量&#xff0c;模块里也能包含可执行的代码. 模块的作用: python中有很多各种不同的模块, 每一个模块都可以帮助我们快速的实现一些功能, 比如实现…

工业4.0视角下:PLC转OPC UA网关的作用

在工业自动化领域&#xff0c;PLC&#xff08;可编程逻辑控制器&#xff09;是常见的控制设备&#xff0c;而OPC UA&#xff08;开放型工业自动化统一架构&#xff09;协议则是一种现代化的通信协议&#xff0c;用在工厂自动化系统中实现设备之间的数据交换和通信。PLC转OPC U…

TensorRT动态形状(Dynamic Shape)出错,官方demo+自己模型运行时出错

(2024.7.2) 使用TensorRT处理动态输入形状推理时出现的错误&#xff0c;本案基于官方demo文件&#xff0c;已解决&#xff1a; TensorRT版本10.0&#xff0c;官方例子使用的是这个https://github.com/NVIDIA/trt-samples-for-hackathon-cn/blob/master/cookbook/01-SimpleDem…

贝叶斯估计(1):期末大乱炖

写在前面&#xff01; 1 先验分布和后验分布 三种信息&#xff1a;总体信息、样本信息、先验信息 总体信息&#xff1a;“总体是正态分布”&#xff1b;样本信息&#xff1a;总体抽取的样本提供的信息&#xff0c;是最新鲜的信息&#xff1b;先验信息&#xff1a;在抽样之前就…