007 Linux fork()函数

前言

本文将会以提问的形式展开向你介绍fork函数

文章重点

关于fork函数,本文重点在于解决以下疑问

疑问一:
为什么fork之前的代码只有父进程执行,然而fork之后的代码父子进程都要执行
疑问二:
1、既然fork之后父子进程会执行一样的代码,那么子进程的意义是什么?
2、为什么fork的两个返回值,会给父进程返回子进程的pid,给子进程返回0
疑问三:
1、为什么fork会有两个返回值
2、如何理解同一个变量,会有不同的值
3、fork之后,父子进程谁先运行

引入fork()函数

linux系统是用c语言写的,所以在linux中创建一个进程实际上也要调用c语言的函数也就是用代码创建进程叫做系统调用,fork函数是Linux系统中实现多进程编程的基础,通过fork函数,可以创建一个子进程,然后在子进程中执行不同的任务,从而实现并行计算和多任务处理。

fork解析一

使用man指令查看fork函数信息
在这里插入图片描述

#include<stdio.h>    
#include<unistd.h>    
#include<sys/types.h>    
int main()    
{    printf("我是一个进程,pid:%d ppid:%d\n",getpid(),getppid());                                                                                                         while(1)    {              fork();                                                          printf("i am a process,pid:%d ppid:%d\n",getpid(),getppid());    sleep(1);    }       return 0;
}   

观察结果
在这里插入图片描述
可以观察到子进程已经被创建出来了(pid为5584)

疑问:为什么fork之前的代码只有父进程执行,然而fork之后的代码父子进程都要执行(观察结果的后两行->父子进程都执行了代码),并且为什么子进程不会从头开始执行父进程的代码?

原因是: 子进程以父进程为模板,把父进程中的大部分属性拷贝给子进程
fork会创建子进程,系统中会多出一个子进程,操作系统以父进程为模板为子进程创建PCB,但是创建的子进程是没有代码和数据的!!目前和父进程共享代码和数据
所以fork之后,父子进程会执行一样的代码,创建出来的子进程并不从头开始执行父进程的代码,而是从fork函数之后的代码开始执行(父进程的大部分属性拷贝给了子进程,包括寄存器的状态->用于记录当前指令的执行位置和保存临时数据)

fork解析二

观察第二第三行分别是父进程和子进程执行的结果
在这里插入图片描述

疑问二:
1、既然fork之后父子进程会执行一样的代码,那么子进程的意义是什么?
2、为什么fork的两个返回值,会给父进程返回子进程的pid,给子进程返回0

引入: fork成功的时候会有两个不同的返回值,给子进程返回0,给父进程返回子进程的pid
为什么要创建子进程呢:我们想让子进程协作父进程完成一些工作,这些工作是单进程解决不了的
可以通过判断fork的返回值,来让父子进程执行不一样的代码,让子进程实现和父进程不一样的功能,比如:我们可以一边玩游戏一边听着音乐,这两个过程就是不同的进程在执行

#include<stdio.h>                                                                                                                                                       
#include<sys/types.h>    
#include<unistd.h>    
int main()    
{    printf("我是一个父进程,我的pid是: %d\n",getpid());    pid_t id = fork();    if(id==0)//子进程的代码片段    {    while(1)    {    printf("我是子进程: pid:%d ppid: %d ret:%d,我在进行下载任务\n",getpid(),getppid(),id);    sleep(1);    }    }    else if(id>0)//父进程的代码片段    {    while(1)    {    printf("我是父进程: pid:%d ppid: %d ret:%d,我在进行播放任务\n",getpid(),getppid(),id);    sleep(1);    }    }return 0;
}

pid_t id = fork();
观察结果:fork成功的时候会有两个不同的返回值,给子进程返回0,给父进程返回子进程的pid
在这里插入图片描述

一个父进程可以创建很多个子进程,然而一个子进程只对应一个父进程,所以fork函数会返回子进程的id给父进程,方便父进程管理它的子进程

fork解析三

1、为什么fork会有两个返回值
2、如何理解同一个变量,会有不同的值
3、fork之后,父子进程谁先运行

在这里插入图片描述

1、创建完子进程后,子进程会共享父进程的代码和数据,很明显return也是一句代码,所以父子进程都会执行return语句,fork函数有两个返回值

pid_t id = fork();
打印id地址
在这里插入图片描述
观察到父子进程的返回值id是不一样的,但是地址却是一样的。
怎么可能同一个变量,同一个地址,会有不同的内容(变量id在父进程和子进程中值不同)呢?

2、进程具有独立性,首先表现在进程各自的PCB运行时不会相互影响,很明显,代码本身只是可读的,所以不是影响代码,但是对于数据来说,父子的数据是可能不同的(可能会被修改)
所以系统是怎样做到让数据在各个进程都自己私有一份的,答案是写时拷贝,数据会在需要使用时被写时拷贝到PCB,然而fork返回值赋值给变量时,本质也是写入,返回时也会发生写时拷贝,所以不同的进程执行的代码中的变量id获取的值不同

3、那么fork之后,父子进程谁先运行?
在调度队列中,cpu会选择一个进程去运行它,谁先被调度谁先运行,所以fork之后父子进程谁现在运行是不确定的,这是由各自进程PCB中的调度信息决定的,比如优先级,算法信息等。

小结

今日的分享就到这里啦,后面将会向你带来进程的状态,优先级,进程地址空间等知识,如果本文存在疏漏或错误的地方还请您能够指出!
在这里插入图片描述

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

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

相关文章

【Copilot】登录报错 Extension activation failed: “No auth flow succeeded.“(VSCode)

问题描述 当尝试在 Visual Studio Code 中登录 GitHub Copilot 插件时&#xff0c;会出现报错的情况&#xff0c;如下图所示&#xff1a; 尽管在浏览器中成功授权了 GitHub 账户&#xff0c;但在返回 VSCode 后仍然报错&#xff0c;如下图所示&#xff1a; 同时&#xff0c;在…

mysql 讲解(1)

文章目录 前言一、基本的命令行操作二、操作数据库语句2.1、创建数据库2.2、删除数据库2.3、使用数据库2.4 查看所有数据库 三、列的数据类型3.1 字符串3.2 数值3.3 时间日期3.4 空3.5 int 和 varchar问题总结&#xff1a; 四、字段属性4.1 UnSigned4.2 ZEROFILL4.3 Auto_InCre…

python的re正则表达式

华子目录 什么是正则表达式元字符字符集字符集与元字符的综合使用 数量规则指定匹配次数边界处理分组匹配贪婪匹配非贪婪匹配re.S转义字符re.search()re.sub()实例常见的匹配模式 什么是正则表达式 正则表达式是一个特殊的字符序列&#xff0c;它能帮助你方便的检查一个字符串…

nmap原理与使用

kali的命令行中可以直接使用 nmap 命令&#xff0c;打开一个「终端」&#xff0c;输入 nmap 后回车&#xff0c;可以看到 nmap 的版本&#xff0c;证明 nmap 可用。 一、端口扫描 扫描主机的「开放端口」&#xff0c;在nmap后面直接跟主机IP&#xff08;默认扫描1000个端口&am…

数据库存储过程

存储过程&#xff1a; 是一组为了完成特定功能的sql语句的集合。类似于函数。 写好了一个存储过程之后&#xff0c;我们可以像函数一样随时调用sql的集合。 复杂的&#xff0c;需要很多sql语句联合执行完成的任务。 存储过程在执行上比sql语句的执行速度要快&#xff0c;效率…

【Spring Boot 源码学习】初识 SpringApplication

Spring Boot 源码学习系列 初识 SpringApplication 引言往期内容主要内容1. Spring Boot 应用程序的启动2. SpringApplication 的实例化2.1 构造方法参数2.2 Web 应用类型推断2.3 加载 BootstrapRegistryInitializer2.4 加载 ApplicationContextInitializer2.5 加载 Applicatio…

计算机底层的秘密 摘抄笔记

https://www.bookstack.cn/read/webxiaohua-gitbook/README.md 大部分是摘抄 机器指令需要加载到内存中执行&#xff0c;因此需要记录下内存的起始地址和长度&#xff1b;同时要找到函数的入口地址并写到PC寄存器中&#xff0c;想一想这是不是需要一个数据结构来记录下这些信…

vue项目路由使用history模式,nginx配置,刷新页面显示404

需要在配置项中添加 try_files $uri $uri/ /index.html;

Technology Strategy Patterns 学习笔记9 - bringing it all together

1 Patterns Map 2 Creating the Strategy 2.1 Ansoff Growth Matrix 和owth-share Matrix 区别参见https://fourweekmba.com/bcg-matrix-vs-ansoff-matrix/ 3 Communicating

Git系列之分支与标签的使用及应用场景模拟

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《Git实战开发》。&#x1f3af;&#x1f3af; &a…

WPF ToggleButton 主题切换动画按钮

WPF ToggleButton 主题切换动画按钮 仿造最近看到的html中的一个效果&#xff0c;大致思路是文章这样&#xff0c;感觉还可以再雕琢一下。 代码如下 XAML: <UserControl x:Class"WPFSwitch.AnimationSwitch"xmlns"http://schemas.microsoft.com/winfx/200…