Linux系统编程——fork函数的使用方法

Linux 系统编程 中,fork() 函数是创建新进程的关键系统调用。fork() 在当前进程(父进程)中创建一个几乎完全相同的子进程。子进程和父进程从调用 fork() 的位置继续执行,但它们是两个独立的进程,每个进程都有自己的进程标识符(PID)和资源。

以下是 fork() 函数的详细使用方法和注意事项。

1. fork() 函数简介

函数原型:
#include <unistd.h>
pid_t fork(void);
  • 返回值

    • 如果 fork() 调用成功,父进程 返回子进程的 PID(正整数),子进程 返回 0。

    • 如果调用失败,返回 -1,错误信息可以通过 errno 获取。

  • PID(进程标识符)

    • 父进程可以通过返回值得到子进程的 PID。

    • 子进程的 PID 是由操作系统自动分配的。

  • 子进程的资源

    • 子进程从父进程复制了几乎所有的资源,包括内存、文件描述符、环境变量等。

    • 子进程有自己的地址空间,与父进程独立运行。


2. fork() 的工作原理

fork() 系统调用会创建一个与父进程几乎相同的子进程。子进程有自己独立的进程 ID(PID),并从 fork() 函数返回。父进程和子进程都从 fork() 之后的位置开始执行。父子进程的 代码、数据、堆、栈 等内容是相同的,但它们有各自的内存空间。

  • 父进程fork() 返回子进程的 PID。

  • 子进程fork() 返回 0。

3. 简单示例

下面是一个简单的 fork() 示例,展示了父子进程的不同返回值。

示例代码:
#include <stdio.h>
#include <unistd.h>int main() {pid_t pid = fork();  // 创建一个子进程if (pid < 0) {// 错误处理,fork() 失败perror("fork failed");return 1;}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);}return 0;
}
说明:
  • fork() 被调用后,父进程和子进程都从同一位置开始执行。

  • 父进程pid 存储子进程的 PID,因此父进程会打印 "This is the parent process" 以及子进程的 PID。

  • 子进程pid 为 0,因此子进程会打印 "This is the child process"。

输出示例:
This is the parent process, PID = 1234, Child PID = 1235
This is the child process, PID = 1235

4. fork() 的使用场景

fork() 函数常用于以下几种场景:

  • 创建子进程:在多进程系统中,通过 fork() 创建子进程来执行并发任务。

  • 执行子程序:父进程创建子进程后,子进程可以通过 exec() 函数系列来执行不同的程序。例如,父进程创建子进程后,子进程可以执行 lscat 等命令。

  • 后台任务:父进程创建子进程后,可以让子进程在后台执行某些任务,父进程继续执行其他任务。


5.fork()创建子进程执行并发任务

我们可以使用fork模拟服务器不断等待用户输入,并且每次得到正确的输入都与之进行交互的场景。

示例:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t pid;int data;while(1){printf("input your data:\n");scanf("%d",&data);if(data == 1){pid = fork();if(pid == 0){while(1){printf("do net request...pid = %d\n",getpid());sleep(3);}}else{}}else{printf("do nothing\n");}}return 0;
}

编译执行后:

input your data:
4
do nothing
input your data:
1
input your data:
do net request...pid = 101459
do net request...pid = 101459
4
do nothing
input your data:
do net request...pid = 101459
do net request...pid = 101459
1
input your data:
do net request...pid = 101460
do net request...pid = 101459
do net request...pid = 101460
1
input your data:
do net request...pid = 101461
do net request...pid = 101459
do net request...pid = 101460
do net request...pid = 101461
do net request...pid = 101459
do net request...pid = 101460
do net request...pid = 101461

从输出可以看到,当系统得到的输入为1时,就会创建一个子进程,子进程会不断地打印“do net request...”并打印出来子进程的PID。子进程不断执行的同时,也不会影响我们重新再对系统进行输入,当得到的输入为1时,就会再次创建一个子进程。

6. fork() 的注意事项

1. 父子进程共享文件描述符

fork() 创建的子进程会继承父进程的所有文件描述符,但文件描述符指向的文件句柄会被子进程和父进程共享。因此,父子进程可以共享文件,但在文件内容修改时要注意同步。

2. 父子进程的资源独立

尽管父子进程最初几乎相同,但它们是独立的。对某一进程的资源(如内存)做出的修改不会影响到另一个进程。

3. 进程的 PID
  • 父进程fork() 返回子进程的 PID。

  • 子进程fork() 返回 0,子进程的 PID 是父进程返回的 PID。

4. fork() 调用失败的处理

fork() 调用可能会失败,特别是在系统资源不足时。此时,fork() 会返回 -1,表示创建子进程失败。需要通过 errno 获取错误原因(如 ENOMEM)。

if (pid < 0) {perror("fork failed");exit(1);
}
5. fork()exit() 配合使用

当父进程或子进程完成任务后,通常会调用 exit() 来终止进程。父进程和子进程的退出不会自动结束另一进程,除非显式调用 exit() 或使用 wait() 等等待机制来同步进程。


7. 进程的父子关系

每个进程都有一个父进程,创建它的进程称为“父进程”。通过 fork(),父进程创建子进程。父进程可以通过 wait() 等函数等待子进程完成,而子进程通过 getppid() 可以获取父进程的 PID。

示例:父进程等待子进程结束
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();  // 创建子进程if (pid < 0) {perror("fork failed");return 1;}if (pid == 0) {// 子进程执行printf("Child process with PID %d\n", getpid());return 0;  // 子进程结束} else {// 父进程等待子进程结束wait(NULL);  // 等待任何子进程结束printf("Parent process with PID %d\n", getpid());}return 0;
}

8. fork()exec() 配合使用

fork() 通常与 exec() 系列函数一起使用。exec() 用于让子进程执行一个新的程序,而不是继续执行父进程中的代码。

示例:父进程创建子进程并执行新的程序
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>int main() {pid_t pid = fork();if (pid < 0) {perror("fork failed");return 1;}if (pid == 0) {// 子进程执行新的程序execlp("/bin/ls", "ls", "-l", NULL);  // 执行 ls -l 命令} else {// 父进程继续执行wait(NULL);  // 等待子进程结束printf("Parent process finished\n");}return 0;
}

总结

  1. fork() 用于创建一个新的子进程,父进程和子进程从 fork() 返回的地方开始继续执行。

  2. 父进程和子进程fork() 调用之后拥有独立的内存空间和资源,但共享文件描述符。

  3. fork() 调用失败 时返回 -1,需要处理错误。

  4. 使用 wait() 可以使父进程等待子进程结束,避免产生僵尸进程。

  5. exec() 系列函数通常与 fork() 配合使用,允许子进程执行新的程序。

fork() 是多进程编程的基础,理解 fork() 的行为和父子进程的关系对于进行系统编程和开发多进程应用非常重要。

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

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

相关文章

LLMs之ChatGPT:《Connecting GitHub to ChatGPT deep research》翻译与解读

LLMs之ChatGPT&#xff1a;《Connecting GitHub to ChatGPT deep research》翻译与解读 导读&#xff1a;这篇OpenAI帮助文档全面介绍了将GitHub连接到ChatGPT进行深度代码研究的方法、优势和注意事项。通过连接GitHub&#xff0c;用户可以充分利用ChatGPT强大的代码理解和生成…

flutter 视频通话flutter_webrtc

flutter 比较热门的库 flutter_webrtc | Flutter package agora_rtc_engine | Flutter package 我使用的是flutter_webrtc 下面是官方推荐的demo库 GitHub - flutter-webrtc/flutter-webrtc-demo: Demo for flutter-webrtc 其中 https://demo.cloudwebrtc.com:8086/ 已经停…

同设备访问php的多个接口会有先后等待问题

同设备访问php的多个接口会有先后等待问题 这个现象的核心原因通常与 PHP 的 Session 锁机制 有关&#xff0c;即使两个接口表面上无关联&#xff0c;也可能因共享 Session 导致请求排队。以下是详细分析&#xff1a; 关键背景&#xff1a;PHP 的 Session 锁机制 PHP 的 Sessi…

【免杀】C2免杀技术(三)shellcode加密

前言 shellcode加密是shellcode混淆的一种手段。shellcode混淆手段有多种&#xff1a;加密&#xff08;编码&#xff09;、偏移量混淆、UUID混淆、IPv4混淆、MAC混淆等。 随着杀毒软件的不断进化&#xff0c;其检测方式早已超越传统的静态特征分析。现代杀软往往会在受控的虚…

【论文阅读】Dip-based Deep Embedded Clustering with k-Estimation

摘要 近年来,聚类与深度学习的结合受到了广泛关注。无监督神经网络,如自编码器,能够自主学习数据集中的关键结构。这一思想可以与聚类目标结合,实现对相关特征的自动学习。然而,这类方法通常基于 k-means 框架,因此继承了诸如聚类呈球形分布等各种假设。另一项常见假设(…

.NET8关于ORM的一次思考

文章目录 前言一、思路二、实现ODBC>SqlHelper.cs三、数据对象实体化四、SQL生成SqlBuilder.cs五、参数注入 SqlParameters.cs六、反射 SqlOrm.cs七、自定义数据查询八、总结 前言 琢磨着在.NET8找一个ORM&#xff0c;对比了最新的框架和性能。 框架批量操作性能SQL控制粒…

CVE-2025-31258 macOS远程视图服务沙箱逃逸漏洞PoC已公开

苹果公司近日针对macOS系统中新披露的CVE-2025-31258漏洞发布补丁&#xff0c;该漏洞可能允许恶意应用程序突破沙箱限制&#xff0c;获取未授权的系统资源访问权限。在安全研究员Seo Hyun-gyu公开概念验证&#xff08;PoC&#xff09;利用代码后&#xff0c;该漏洞已在macOS Se…

21.第二阶段x64游戏实战-分析采集物偏移

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 上一个内容&#xff1a;20.第二阶段x64游戏实战-代码实现遍历周围 上一个内容里把遍历周围的npc和玩家…

2025年全新 GPT 4.5 AI 大模型 国内免费调用

一、中转账号注册 第一步&#xff1a;打开宙流AI中转站&#xff0c;网站地址如下&#xff1a; 宙流AI中转站 按照上图中的操作步骤&#xff0c;通过邮箱进行账号注册&#xff0c;注册完毕后&#xff0c;网站初始会分配0.4刀的免费额度&#xff0c;获取额度后&#xff0c;即可…

基于事件驱动和策略模式的差异化处理方案

一、支付成功后事件驱动 1、支付成功事件 /*** 支付成功事件** author ronshi* date 2025/5/12 14:40*/ Getter Setter public class PaymentSuccessEvent extends ApplicationEvent {private static final long serialVersionUID 1L;private ProductOrderDO productOrderDO;…

简述Web和HTTP

目录 HTTP概述 非持续连接和持续连接 非持续连接 持续连接 HTTP报文格式 HTTP请求报文 HTTP响应报文 用户与服务器的交互&#xff1a;cookie Web缓存 条件GET方法 Web 即万维网&#xff0c;是一个基于超文本和 HTTP 协议的全球性信息系统&#xff0c;通过浏览器访问…

基于STM32的LCD信号波形和FFT频谱显示

一、项目准备 主要利用LCD驱动中的画点和画连线函数&#xff0c;驱动是正点原子给我写好了的画点和画线的函数等些相关函数 void LCD_Draw_Circle(u16 x0,u16 y0,u8 r); //画圆 void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //画线 二、画波形图函数实…

Go 语言即时通讯系统开发日志-day1:从简单消息收发 Demo 起步

Go语言即时通讯系统开发日志day1&#xff0c;主要模拟实现的一个简单的发送消息和接受消息的小demo&#xff0c;因为也才刚学习go语言的语法&#xff0c;对go的json、net/http库了解不多&#xff0c;所以了解了一下go语言的encoding/json库和net/http库&#xff0c;以及websock…

基于vllm-ascend的华为atlas大模型部署

vllm-ascend介绍&#xff1a; vLLM 昇腾插件 (vllm-ascend) 是一个让vLLM在Ascend NPU无缝运行的后端插件。 此插件是 vLLM 社区中支持昇腾后端的推荐方式。它遵循[RFC]: Hardware pluggable所述原则&#xff1a;通过解耦的方式提供了vLLM对Ascend NPU的支持。 使用 vLLM 昇腾…

贝叶斯优化Transformer融合支持向量机多变量时间序列预测,Matlab实现

贝叶斯优化Transformer融合支持向量机多变量时间序列预测&#xff0c;Matlab实现 目录 贝叶斯优化Transformer融合支持向量机多变量时间序列预测&#xff0c;Matlab实现效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.BO-TransformerSVM多变量时间序列预测&#xff0c…

状压DP总结

前言 一般来讲 n n n 数据范围在 10 ~ 25 之间都是可以进行状态压缩的 -> 2 n 2^n 2n 状压 The 2024 Shanghai Collegiate Programming Contest Problem G.象棋大师 知识点&#xff1a;线性DP&#xff0c;状压DP&#xff0c;预处理 辅助转移的技巧 首先看到 n*n 的方格…

SQLite 转换为 MySQL 数据库

一、导出 SQLite 数据库 1. 使用 SQLite 命令行工具 • 打开终端&#xff08;在 Linux 或 macOS 上&#xff09;或命令提示符&#xff08;在 Windows 上&#xff09;。 • 输入sqlite3 your_database_name.db&#xff08;将 your_database_name.db 替换为你的 SQLite 数据库…

【技巧】使用UV创建python项目的开发环境

回到目录 【技巧】使用UV创建python项目的开发环境 0. 为什么用UV 下载速度快、虚拟环境、多版本python支持、清晰的依赖关系 1. 安装基础软件 1.1. 安装python 下载地址&#xff1a;https://www.python.org/downloads/windows/ 1.2. 安装UV > pip install uv -i ht…

Java SpringMVC 和 MyBatis 整合项目的事务管理配置详解

目录 一、事务管理的基本概念二、在 SpringMVC 和 MyBatis 整合项目中配置事务管理1. 配置数据源2. 配置事务管理器3. 使用事务注解4. 配置 MyBatis 的事务支持5. 测试事务管理三、总结在企业级应用开发中,事务管理是确保数据一致性和完整性的重要机制。特别是在整合了 Spring…

Nakama:让游戏与应用更具互动性和即时性

在现代游戏和应用程序开发中,实现社交互动和实时功能已成为用户体验的核心需求。为满足这种需求,许多开发者正转向分布式服务器技术,在这些技术中,Nakama 构建起了一座桥梁。Nakama 是一个开源的分布式服务器,专门为社交和实时游戏及应用程序设计,为开发者提供了强大的工…