Linux 第十一章

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

❤️‍🔥专栏系列:线性代数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是不是父进程定义的变量?肯定是,保存就是数据

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

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

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

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

相关推荐

  1. Linux:Samba文件共享服务

    2024-04-29 07:52:02       27 阅读
  2. Linux

    2024-04-29 07:52:02       32 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-29 07:52:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-29 07:52:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-04-29 07:52:02       82 阅读
  4. Python语言-面向对象

    2024-04-29 07:52:02       91 阅读

热门阅读

  1. am62x linux sdk环境搭建

    2024-04-29 07:52:02       29 阅读
  2. Docker安装Elasticsearch

    2024-04-29 07:52:02       36 阅读
  3. Rust特征

    2024-04-29 07:52:02       34 阅读
  4. 行列视平台的应用

    2024-04-29 07:52:02       32 阅读
  5. 微信小程序常用的api

    2024-04-29 07:52:02       34 阅读
  6. CMUS狮身人面像(四)-构建语言模型

    2024-04-29 07:52:02       30 阅读
  7. python 贪吃蛇

    2024-04-29 07:52:02       27 阅读
  8. c/c++传值和传引用的区别

    2024-04-29 07:52:02       31 阅读