Linux 第十一章

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

目录

fork

事例

一个函数,竟然有两个返回值???

调用 fork() 后会产生以下结果:

fork的一般写法

 fork的应用

fork的原理

fork干了什么事

为什么fork会有两个返回值

为什么fork的两个返回值,会给父进程返回子进程pid,给子进程返回0?

fork之后,父子进程谁先运行?

如何理解同一个变量,会有不同的值?


fork

fork() 系统调用是Unix和类Unix操作系统(包括Linux)中的一个重要系统调用之一。它用于创建一个新的进程,称为子进程,该子进程是调用进程的副本。

fork() 的一般形式如下:

#include <unistd.h> pid_t fork(void);
其中 pid_t 是一个整数类型,通常是int,表示进程ID。

调用 fork() 后,操作系统会复制父进程的所有内容(包括代码、数据等),然后在子进程中开始执行。这样就创建了两个完全独立的进程,它们可以同时运行不同的代码。

事例

[BCH@hcss-ecs-6176 9_23]$ cat code.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
        printf("我是一个父进程,我的pid%d,ppid:%d\n",getpid(),getppid());
        //创建子进程!,bash他也是用c语言写的,命令行启动的进程,都是bash的子进程,大概估摸着,bash源代码中创建子进程用的就是这个fork()
        fork();
        printf("我是一个进程,我的pid%d,ppid:%d\n",getpid(),getppid());//这个函数只调用了一次
        sleep(1);
}

程序运行:
[BCH@hcss-ecs-6176 9_23]$ ./mycode
我是一个父进程,我的pid24782,ppid:21864
我是一个进程,我的pid24782,ppid:21864
我是一个进程,我的pid24783,ppid:24782

总结:只有父进程会执行fork之前的代码(一定),fork之后,父子进程都要执行后续的代码

一个函数,竟然有两个返回值???

在 Linux 中,fork() 是一个系统调用,用于创建一个新的进程。当调用 fork() 时,操作系统会复制当前进程的副本,并将其作为新进程运行。这个新的进程称为子进程,而调用 fork() 的原始进程称为父进程。

调用 fork() 后会产生以下结果:

* 如果调用成功,则在父进程中返回子进程的 ID,而在子进程中返回 0。

* 如果调用失败,则在父进程中返回 -1,表示出现了错误。

父进程和子进程将在 fork() 调用之后的代码行处继续执行,但是它们拥有各自独立的进程空间和资源。子进程是父进程的一个副本,包括内存、文件描述符等。子进程可以执行不同的指令,或者通过调用 exec() 系列函数来执行其他程序。

fork的一般写法

1.我们为什么要创建子进程

我们想让子进程协作父进程完成一些工作,这些工作是单进程解决不了的

例如:我们的音乐,想要边下载,边播放

2.我们创建子进程是为了让子进程和我父进程做一样的事情吗?

肯定不是!

我们创建子进程,就是为了让子进程和父进程做不一样的事情,执行不一样的代码

我可以通过fork的返回值,判断谁是父,谁是子,然后让他们执行不同的代码片段!!

 fork的应用

[BCH@hcss-ecs-6176 9_23]$ cat code.c
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
        
        printf("我是一个父进程,我的pid%d,ppid:%d\n",getpid(),getppid());
        pid_t id=fork();
        //fork之后,用if进行分流
        if(id<0)return 1;
        else if(id==0)
        {
                //child
                while(1)
                {
                        printf("我是子进程:pid:%d,ppid:%d,ret:%d,我正在执行下载任务\n",getpid(),getppid(),id);
                        sleep(1);
                }
        }
        else
        {
                //parent
                while(1)
                {               
                        printf("我是父进程:pid:%d,ppid:%d,ret:%d,我正在执行播放任务\n",getpid(),getppid(),id);
                        sleep(1);
                }
        }
        return 0;
}

[BCH@hcss-ecs-6176 9_23]$ ./mycode
我是一个父进程,我的pid10090,ppid:21864
我是父进程:pid:10090,ppid:21864,ret:10091,我正在执行播放任务
我是子进程:pid:10091,ppid:10090,ret:0,我正在执行下载任务
我是父进程:pid:10090,ppid:21864,ret:10091,我正在执行播放任务
我是子进程:pid:10091,ppid:10090,ret:0,我正在执行下载任务
我是父进程:pid:10090,ppid:21864,ret:10091,我正在执行播放任务
我是子进程:pid:10091,ppid:10090,ret:0,我正在执行下载任务
^C

总结:奇怪的现象
1)if和else里的代码同时执行
2)两个死循环同时运行

fork的原理

fork干了什么事

为什么fork会有两个返回值

如果一个函数已经到return了,它的核心工作做完了吗?

做完了。

fork就是一个函数

fork之后代码共享!!!

return也是代码,return也要被共享!!

父进程要被调度,就要执行return

子进程要被调度,就要执行return

为什么fork的两个返回值,会给父进程返回子进程pid,给子进程返回0?

因为子进程的pid是唯一标识子进程的,父进程可以通过子进程的pid对子进程进行管理

1) 对于父进程:fork() 返回子进程的进程 ID(PID),即一个正整数值。父进程可以根据这个返回值来管理和控制子进程,例如等待子进程结束、发送信号给子进程等。父进程可以使用这个 PID 来识别和跟踪它创建的子进程。

2)对于子进程:由于 fork() 是在子进程中调用的,所以子进程并不需要父进程的 ID。为了简化子进程的处理逻辑,fork() 特意将其返回值设为 0。这样,在子进程中通过检查返回值是否为 0 可以确定自己是子进程,并在之后的代码中执行特定的子进程逻辑。

fork之后,父子进程谁先运行?

1)创建完成子进程,只是一个开始,创建完成子进程之后,系统的其他进程,父进程和子进程,接下来要被调度执行的!

2)当父进程的pcb都被创建并在 运行队列 中排队的时候,哪一个进程的pcb先被选择调度,那个进程就先运行!!

3)由各自pcb中的调度信息(时间片、优先级等)+调度器的算法共同决定的,总而言之,由操作系统自主决定!!!

所以父子进程谁先运行是不确定的

如何理解同一个变量,会有不同的值?

如果启动一个qq、微信、浏览器,这些都是进程,杀掉微信进程,qq进程还在吗?浏览器进程还在吗?还在!!

如果我们,父子进程,父进程被杀掉,子进程还在吗?或者返回过来?

还在!!

总结:进程之间运行的时候,是具有独立性的!无论是什么关系!

这个独立性是怎么做到的呢?

进程的独立性,首先表现在有各自的pcb,进程之间不会影响!代码本身是只读的,是不会影响代码!数据父子会修改的!代码共享,数据各自进程必须想办法各自私有一份!!

如何私有一份数据呢?

写时拷贝

创建子进程的时候,以浅拷贝的方式进行共享代码

父子任何一个尝试对他做写入时,把要修改的变量以深拷贝的形式给拷贝一份。

fork返回的值id,返回的本质是不是写入?是写入

id是不是父进程定义的变量?肯定是,保存就是数据

返回的时候,发生了写时拷贝

怎么同一个变量,同一个地址,会有不同内容?

这个地址,绝对不是物理地址!

 🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

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

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

相关文章

BUUCTF-WEB2

[SUCTF 2019]EasySQL1 1.启动靶机 2.寻找注入点和注入方法 随便输入一个字母&#xff0c;没有回显 随便输入一个数字&#xff0c;发现有回显&#xff0c;并且回显结果一样 3.堆叠注入 1; show databases; #查看数据库 1; show tables; #查看数据表 里面有个flag 1;set …

Three.js和Cesium.js中坐标

在了解Three.js和Cesium.js前先了解并弄清楚图形学关于空间的基本概念流程&#xff1a; 计算机图形学 图形学中涉及到多个坐标空间&#xff0c;这些空间之间的变换是图形渲染中的核心部分。下面是一些常见的图形学空间及其变换顺序&#xff1a; 对象空间&#xff08;Object Sp…

【完整指南】如何在Visual Studio Code中轻松运行Llama 3模型?

Meta 发布了最新的开源语言模型Llama 3。因为它是开源的&#xff0c;你可以下载这个模型&#xff0c;并在自己的电脑上运行。 我清楚&#xff0c;你可能会想&#xff0c;在个人笔记本上运行一个拥有80亿参数的AI模型似乎只有技术高手才能做到。但别担心&#xff01;这篇文章会…

MATLAB 运算符

MATLAB 运算符 运算符是一个符号&#xff0c;告诉编译器执行特定的数学或逻辑操作。MATLAB设计为主要在整个矩阵和数组上运行。因此&#xff0c;MATLAB中的运算符既可以处理标量数据&#xff0c;也可以处理非标量数据。MATLAB允许以下类型的基本运算- 算术运算符 关系运算符…

前端复习资料

前端复习资料 落叶的位置&#xff0c;谱出一首诗&#xff0c;时间在消逝&#xff0c;我们的故事。 这篇文章呢&#xff0c;整理写给需要的前端同学的。 核心知识&#xff0c;必须掌握的&#xff0c;也是最基础的&#xff0c;譬如浏览器模型&#xff0c;渲染原理&#xff0c;JS…

网页模版如何用

现在的网页模版已经得到了许多人的喜爱和使用。随着人们对互联网的需求不断增加&#xff0c;更多的公司和组织需要拥有自己的网站&#xff0c;以推广他们的品牌和服务。而网页模版为他们提供了一个简单而高效的方法来创建自己的网站。 网页模版是预先设计好的网站模板&#xff…

【数据分析】NumPy

文章目录 [toc]ndarray的创建np.array()方法np.arange()方法np.zeros()方法np.ones()方法np.full()方法np.eye()方法np.random模块np.random.random()方法np.random.randint()方法np.random.choice()方法np.random.shuffle()方法 ndarray的属性ndarray.dtypendarray.ndimndarra…

初识BootStrap

目录 前言: 1.Bootstrap的特点包括&#xff1a; 1.1响应式设计&#xff1a; 1.2组件丰富&#xff1a; 1.3易于定制&#xff1a; 1.4兼容性良好&#xff1a; 1.5强大的社区支持&#xff1a; 1.6一致的样式和布局&#xff1a; 1.7 插件和扩展性 2.初识Ajax: 2.1同步请求…

Linux——(关于权限常见的3个问题)

文章目录 1.修改文件或者目录的拥有者和所属组1.1chown指令1.2chgrp指令 2.常见的权限三个问题2.1对应一个目录&#xff0c;如果要进入&#xff0c;需要什么权限&#xff1f;2.2为什么我们创建的文件默认权限不是7772.2.1关于Linux下的权限掩码 2.3文件能否被删除取决于什么2.3…

Paddle OCR v4 微调训练文字识别SVTRNet模型实践

文字识别步骤参考&#xff1a;https://github.com/PaddlePaddle/PaddleOCR/blob/main/doc/doc_ch/recognition.md 微调步骤参考:https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.7.1/doc/doc_ch/finetune.md 训练必要性 原始模型标点符号和括号容易识别不到 数据…

【kettle004】kettle访问本地MySQL数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下MySQL关系数据库相关知识体系 3.欢迎批评指正&#xff0c;跪谢一键三连&…

大模型微调:技术迭代与实践指南

在人工智能领域&#xff0c;大模型&#xff08;LLM&#xff09;的微调是一个关键过程&#xff0c;它使模型能够适应特定的任务和数据集。微调是深度学习中用于改进预训练模型性能的重要技术。通过在特定任务的数据集上继续训练&#xff0c;模型的权重被更新以更好地适应该任务。…

揭秘工业大模型:从人工智能小白到技术先锋

工业大模型的五个基本问题 信息化时代&#xff0c;数字化转型成为企业提升营运效率、应对经营风险和提升核心竞争力的重要途径。在此过程中&#xff0c;数据作为一种客观存在的资源&#xff0c;所产生的价值日益凸显。党的十九届四中全会从国家治理体系和治理能力现代化的高度将…

详解Qt绘图机制

Qt框架以其强大的图形界面功能著称&#xff0c;其中绘图机制是构建丰富视觉效果的关键。本文将详细介绍Qt中的绘图机制&#xff0c;包括绘图基础、绘图设备、绘图工具及高级特性&#xff0c;并通过实战C代码示例&#xff0c;带你领略Qt绘图的魅力。 绘图基础 Qt的绘图操作主要…

vs2019 - release版中_DEBUG宏生效的问题

文章目录 vs2019 - release版中_DEBUG宏生效的问题概述笔记总结END vs2019 - release版中_DEBUG宏生效的问题 概述 在加固程序&#xff0c;需要去掉PE的字符串表中和逻辑相关的字符串。 编译成release版后&#xff0c;用IDA看&#xff0c;还是发现有debug版才有的字符串。 那…

gitee关联picgo设置自己的typora_图床

一&#xff1a;去gitee官网创建仓库&#xff1a;typora_图床 1.百度搜索关键字&#xff1a;gitee&#xff0c;进入官网 2.进入gitee登录或者注册自己的账号 3.进入主页后&#xff0c;点击右上方 4.点击新建仓库 5.设置仓库名&#xff1a;typora_图床 6.点击5的创建&#xff0…

<计算机网络自顶向下> Internet Protocol(未完成)

互联网中的网络层 IP数据报格式 ver: 四个比特的版本号&#xff08;IPV4 0100, IPV6 0110&#xff09; headlen&#xff1a;head的长度&#xff08;头部长度字段&#xff08;IHL&#xff09;指定了头部的长度&#xff0c;以32位字&#xff08;4字节&#xff09;为单位计算。这…

echarts实现水滴图

使用echarts实现水滴图 引入依赖&#xff0c;echarts-liquidfill3兼容echarts5; 安装依赖 "echarts": "^5.4.3","echarts-liquidfill": "^3.1.0",npm install echarts-liquidfill3.1.0 -S实现的效果图 构建一个水滴图的页面 <tem…

基于Spring Boot的商务安全邮件收发系统设计与实现

基于Spring Boot的商务安全邮件收发系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 已发送效果图&#xff0c;用户可以对已发送信息…

4.28总结

对部分代码进行了修改&#xff0c;将一些代码封装成方法&#xff0c;实现了头像功能&#xff0c;创建一个本地字节输入流 fileinputSteam 对象&#xff0c;构造方法中绑定读取的数据源&#xff0c;创建一个socket对象&#xff0c;构造方法中绑定服务器的IP地址和端口号使用sock…
最新文章