Linux 第十一章

本文详细介绍了Linux中的fork系统调用,包括其功能、返回值含义、父子进程执行顺序以及数据独立性实现机制,通过实例演示展示了fork的用法和原理。
摘要由CSDN通过智能技术生成

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

❤️‍🔥专栏系列:线性代数C初学者入门训练题解CC的使用文章「初学」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是不是父进程定义的变量?肯定是,保存就是数据

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值