🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,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是不是父进程定义的变量?肯定是,保存就是数据
返回的时候,发生了写时拷贝
怎么同一个变量,同一个地址,会有不同内容?
这个地址,绝对不是物理地址!
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸