P10 Linux进程编程 fork创建子进程

目录

前言 

 01 fork()创建子进程

示例 1使用 fork()创建子进程。

02 fork创建新进程时发生了什么事?

 2.1 父、子进程中对应的文件描述符指向了相同的文件表 


前言 

                              

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨ 

🔥 推荐专栏2: 《C++_@ChenPi的博客-CSDN博客》✨✨✨

🛸推荐专栏3: ​​​​​​《链表_@ChenPi的博客-CSDN博客 》 ✨✨✨
🌺本篇简介  :  上一章我们讲了Linux进程的概念以及获取进程ID号和获取父进程的ID

                          这一章我们引进新的概念,父子进程

Linux 是一个多用户多任务的操作系统,每个用户可以同时运行多个程序

进程是程序运行的主体,包括进程的创建,调度和消亡的整个过程

当用户执行一个指令或者启动一个程序时,就创建了一个进程

一个运行的程序也可能有多个进程。

每个进程将被分配各种资源    

 01 fork()创建子进程

一个现有的进程可以调用 fork()函数创建一个新的进程,

调用 fork()函数的进程称为父进程,

由 fork()函 数创建出来的进程被称为子进程(child process),

fork()函数原型如下所示(fork()为系统调用):

2.1 fork()函数原型:

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

返回值: 

  1. 失败返回-1 不创建子进程,并设置 errno 
  2. 父进程的返回值pid为子进程的pid号,子进程的返回值为0

在诸多的应用中,创建多个进程是任务分解时行之有效的方法

  1. 譬如,某一网络服务器进程可在监听客 户端请求的同时,为处理每一个请求事件而创建一个新的子进程,与此同时,服务器进程会继续监听更多的 客户端连接请求
  2. 在一个大型的应用程序任务中,创建子进程通常会简化应用程序的设计,同时提高了系统 的并发性(即同时能够处理更多的任务或请求多个进程在宏观上实现同时运行)。

理解 fork()系统调用的关键在于,完成对其调用后将存在两个进程,

一个是原进程(父进程)、另一个 则是创建出来的子进程,

并且每个进程都会从 fork()函数的返回处继续执行,会导致调用 fork()返回两次值,

子进程返回一个值、父进程返回一个值,所以fork返回值后面的代码块也会调用两次

在程序代码中,可通过返回值来区分是子进程还是父进程。

fork()调用成功后,将会在父进程中返回子进程的 PID,而在子进程中返回值是 0;

如果调用失败,父进 程返回值-1,不创建子进程,并设置 errno。

fork()调用成功后,子进程和父进程会继续执行 fork()调用之后的指令,子进程、父进程各自在自己的进程空间中运行。

事实上,子进程是父进程的一个副本

  1. 譬如子进程拷贝了父进程的数据段、堆、栈以及继承 了父进程打开的文件描述符
  2. 父进程与子进程并不共享这些存储空间
  3. 这是子进程对父进程相应部分存储 空间的完全复制
  4. 执行 fork()之后,每个进程均可修改各自的栈数据以及堆段中的变量,而并不影响另一个进程

示例 1使用 fork()创建子进程。

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
 
int main()
{
    int pid =  fork(); //父进程的返回值pid为子进程的pid号,子进程的返回值为0
    switch (pid)
    {
        case -1:
            printf("fork error\n");
            break;
        case 0:
            printf("this is child ;PID = %d\n",getpid());
            break;
        default:
            printf("this is father;PID = %d\n",getpid());
            break;
    }
 
    return 0;
}

 

 从打印结果可知,fork()之后的语句被执行了两次,所以 switch…case 语句被执行了两次

  1. 第一次进入 到了"case 0"分支,表示进入子进程
  2. 第二次进入到了 default 分支,表示当前处于父进程
  3. 父进程的返回值pid为子进程的id号,子进程的返回值为0 

02 fork创建新进程时发生了什么事?

调用 fork()函数之后,子进程会获得父进程所有文件描述符的副本

这些副本的创建方式类似于 dup(), 这也意味着父、子进程对应的文件描述符均指向相同的文件表,如下图所示:

由此可知

子进程拷贝了父进程的文件描述符表,使得父、子进程中对应的文件描述符指向了相同的文件表

也意味着父、子进程中对应的文件描述符指向了磁盘中相同的文件,

因而这些文件在父、子进程间实 现了共享,

譬如,如果子进程更新了文件偏移量,那么这个改变也会影响到父进程中相应文件描述符的位置 偏移量。  

 2.1 父、子进程中对应的文件描述符指向了相同的文件表 

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define MY_FILE "./file.txt"

int main()
{
	char buf [128];
	int fd = open(MY_FILE,O_RDWR|O_CREAT,0600);
	if(-1 == fd)
	{
		perror("open error? :");
		exit(-1);
	}
	int pid = fork();
	switch (pid)
	{
		case -1:
			printf("fork error\n");
			break;
		case 0:
			for(int i = 0;i<4;i++)
				write(fd," child",strlen(" child"));
			close(fd);
			break;
		default:
			for(int i = 0;i<4;i++)
				write(fd," father",strlen(" father"));
			close(fd);
			break;
	}
	return 0;
}

上述代码中,父进程 open 打开文件之后,才调用 fork()创建了子进程,

所以子进程了继承了父进程打 开的文件描述符 fd,我们需要验证的便是两个进程对文件的写入操作是分别各自写入、还是每次都在文件 末尾接续写入

有上述测试结果可知,此种情况下

父、子进程分别对同一个文件进行写入操作,结果是接续写

不管是父进程,还是子进程,在每次写入时都是从文件的末尾写入很像使用了 O_APPEND 标志的效果。

其原 因也非常简单

子进程继承了父进程的文件描述符,两个文件描述符都指向了一个相同的文件表,意味着它们的文件偏移量是同一个、绑定在了一起,相互影响,子进程改变了文件的位置 偏移量就会作用到父进程,同理,父进程改变了文件的位置偏移量就会作用到子进程

但是执行结果不一定是父进程先执行或者子进程先执行,这个不一定的,这个要看系统的调度了 
 

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

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

相关文章

[Linux] yum安装分布式LNMP架构

1. 在一台主机安装nginx&#xff08;192.168.136.120&#xff09; 1.1 搭建nginx相关的yum源 cd /yum.repos.d mkdir bak mv *.repo bak vim /etc/yum.repos.d/nginx.repo [nginx-stable] namenginx stable repo baseurlhttp://nginx.org/packages/centos/7/$basearch/ gpgche…

题解:CF1902A. Binary Imbalance

题解&#xff1a;CF1902A. Binary Imbalance 先给个题目链接。 题目翻译&#xff08;由“CodeForces Better&#xff01;”和“DeepL 翻译”提供&#xff09;&#xff1a; 我们知道&#xff0c;如果初始字符串中“0”的个数就大于“1”的个数&#xff0c;答案肯定是YES&…

【二分答案法】Leetcode相关题目解析

题目&#xff1a;162. 寻找峰值 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 题目分析&#xff1a; &#xff08;1&#xff09;据题知&#xff0c;索引-1、索引n&#xff08;n为数组长度&#xff09;处的元素都默认为无穷小&#xff0c;我们可以在一开始特判…

软件设计师——操作系统(一)

&#x1f4d1;前言 本文主要是【操作系统】——软件设计师——操作系统的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

鸿蒙开发组件之ForEach列表

一、ForEach函数 ForEach函数是一个迭代函数&#xff0c;需要传递两个必须参数和一个可选参数。主要通过迭代来获取参数arr中的数据不断的生成单个Item来生成鸿蒙中的列表样式 二、先创建单个的Item的UI 通过嵌套Row与Column来实现单个Item的UI。例如图中没有折扣的可以看成一…

Pandas中DataFrame对象的创建与常用属性方法(第2讲)

Pandas中DataFrame对象的创建与常用属性方法(第2讲)         🍹博主 侯小啾 感谢您的支持与信赖。☀️ 🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔ꦿ🌹꧔…

【Docker】swarm stack部署多service应用

前面我们已经学习过了Docker Compose&#xff0c;它可以用来进行一个完整的应用程序相互依赖的多个容器的编排的&#xff0c;但是缺点是只能在单机模式使用&#xff0c;不能在分布式多机器上使用&#xff1b;前面我们也学习了Docker swarm&#xff0c;它可以将单个服务部署为多…

鸿蒙生态开发就业前景到底好不好

鸿蒙生态开发是指基于华为自主研发的操作系统鸿蒙&#xff08;HarmonyOS&#xff09;进行应用程序开发和生态建设。目前&#xff0c;鸿蒙生态开发的前景非常好&#xff0c;原因如下&#xff1a;做鸿蒙应用开发到底学习些啥&#xff1f; (qq.com) 1&#xff1a;政府支持&#x…

万界星空科技mes系统中看板管理

我们很多企业现在都有大屏&#xff0c;那到底万界星空科技低代码云mes系统管理中看板管理有什么作用&#xff1f;我总结了几条: 1.提高车间的生产效率 2.有效的监控设备运行状况 3.控制生产线运行 4.增加和改善用户体验 5.提高工作效率和工作安全性

综述 2019-Genome Biology:非比对方法的benchmark

Zielezinski, Andrzej, et al. "Benchmarking of alignment-free sequence comparison methods." Genome biology 20.1 (2019): 1-18. Benchmarking of alignment-free sequence comparison methods | Genome Biology | Full Text 被引次数&#xff1a;170&#xff…

【算法通关村】链表反转经典问题解析

&#x1f6a9;本文已收录至算法学习之旅 一.基础反转 我们通常有两种方法反转链表&#xff0c;一种是直接操作链表实现反转操作&#xff0c;一种是建立虚拟头节点辅助实现反转操作。 力扣习题链接&#xff1a;206. 反转链表 (1) 直接操作实现反转 我们需要一个变量pre来保…

代码随想录算法训练营第45天| 139.单词拆分 多重背包

JAVA代码编写 139.单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 **注意&#xff1a;**不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 示例 1&#xff1a; 输入: s &…

如何利用人工智能+物联网技术实现自动化设备生产

随着科技的发展与行业竞争的日益激烈&#xff0c;制造业也逐渐走向智能化发展。制造业的改革是利用物联网技术和自动化设备&#xff0c;实现生产线的智能化和自适应生产&#xff0c;优化生产流程&#xff0c;提高生产效率和质量&#xff0c;为企业创造更大的价值。 方案概述 智…

Linux 压缩、文件传输与安装

目录 1. 压缩 1.1 tar 1.2 gzip 1.3 zip 1.4 rar 2 文件传输 2.1 网站下载 2.2 scp 传输 2.3 rz 和 sz 2.4 xftp 3.安装 3.1 编译安装 &#xff08;ngnix&#xff09; 3.2 rpm 安装 3.3 yum 安装 1. 压缩 1.1 tar 使用 tar 压缩文件时&#xff0c;会保留源文件…

使用MetaMask + Ganache搭建本地私有网络并实现合约部署与互动

我使用Remix编写合约&#xff0c;MetaMask钱包工具和Ganache搭建了一个私有网络&#xff0c;并且实现了合约的部署和互动。 在前面的博客中提到了 Remix在线环境及钱包申请 以及 Solidity的基本语法 &#xff0c;没看过的小伙伴可以点击链接查看一下&#xff0c;都是在本专栏下…

智能时代:互联网+如何改变我们的生活与工作

引言 随着科技的不断进步和互联网的普及&#xff0c;我们正处在一个智能时代。这个时代被互联网所定义&#xff0c;它深刻地改变了我们的生活和工作方式。从社交互动到日常工作&#xff0c;智能时代的影响无处不在&#xff0c;给人们带来了前所未有的变革和机遇。 互联网的涌…

模电·放大电路的分析方法——图解法

放大电路的分析方法——图解法 静态工作点的分析电压放大倍数的分析波形非线性失真的分析直流负载线与交流负载线图解法的适用范围 在实际测出放大管的输入特性、输出特性和已知放大电路中其它各元件参数的情况下&#xff0c;利用作图的方法对放大电路进行分析即为图解法。 静…

FacetWP WordPress网站高级筛选过滤插件(含所有扩展)

点击阅读FacetWP WordPress网站高级筛选过滤插件原文 FacetWP WordPress网站高级筛选过滤插件向电子商务网站、资源库、搜索页面等添加分面搜索。FacetWP 的过滤元素&#xff08;称为 facets&#xff09;动态调整以适应用户输入。这有助于防止出现“未找到结果”&#xff0c;从…

OpenSSL 编程指南

目录 前言初始化SSL库创建SSL 上下文接口(SSL_CTX)安装证书和私钥加载证书(客户端/服务端证书)加载私钥/公钥加载CA证书设置对端证书验证例1 SSL服务端安装证书例2 客户端安装证书创建和安装SSL结构建立TCP/IP连接客户端创建socket服务端创建连接创建SSL结构中的BIOSSL握手服务…

【MATLAB源码-第99期】基于matlab的OFDM系统卡尔曼滤波(kalman)信道估计,对比LS,MMSE。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 卡尔曼滤波器&#xff08;Kalman Filter&#xff09;是一种有效的递归滤波器&#xff0c;它能够从一系列的含有噪声的测量中估计动态系统的状态。在无线通信领域&#xff0c;尤其是在正交频分复用&#xff08;OFDM&#xff0…
最新文章