当前位置:首页 » 《关于电脑》 » 正文

【Linux】fork函数

23 人参与  2024年10月26日 10:40  分类 : 《关于电脑》  评论

点击全文阅读


?个人主页:Yui_
?Linux专栏:Linux
?C语言笔记专栏:C语言笔记
?数据结构专栏:数据结构
?C++专栏:C++

文章目录

1. 进程创建2. fork的执行情况3.写时拷贝4.fork的常规用法5.fork调用失败的原因

1. 进程创建

在英文释义里fork的意思为派生分支到的意思,是UNIX或类UNIX中的分叉函数。该函数也是UNIX中派生新进程的唯一方法,不熟悉fork,就不可能熟悉多线程编程。因此熟悉好fork函数也是程序员的必备技能之一。
linux环境下我们可以使用man fork来了解它的功能:
fork

根据文档我们可以知道,fork是用来创建一个新进程的,将新创建的进程称为子进程。子进程可以和原进程同时进行,原进程即为父进程。

#include <unistd.h> //fork头文件int main(){pid_t id = fork();//pid_t是系统封装的一个宏,本质上是intreturn 0;}

关于返回值
子进程中返回0,父进程中返回子进程id,出错返回-1。

pid_t id = fork();//因为存在出错情况,所以我们在使用时是需要进行错误判断的if(id < 0){perror("fork");exit(1);}...

提问:为什么子进程返回0,而父进程返回子进程id呢?
答:因为子进程只有唯一的父进程,不需要额外标识就可以找到。而父进程可以存在多个子进程,需要额外的标识才能找到这个新创建的子进程。

验证父子进程的返回情况:

#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>int main(){printf("Before: pid is %d\n",getpid());pid_t id = fork();if(id < 0){perror("fork");exit(1);}if(id == 0){//childprintf("After: pid is %d,fork return %d\n",getpid(),id);}else if(id != 0){//parentprintf("After: pid is %d,fork return %d\n",getpid(),id);}return 0;}//打印结果:/*Before: pid is 25514After: pid is 25514,fork return 25515After: pid is 25515,fork return 0*/

2. fork的执行情况

进程调用fork后,当控制转移到内核的fork代码后,内核做:

分配新的内存块和内核数据结构给子进程。将父进程部分数据结构内容拷贝到子进程。添加子进程到系统进程列表中。fork返回,开始调度器调度。
在上面的执行情况中,我们也看到了if 和 else if居然同时执行了,在正常情况下是匪夷所思的,但正常情况下是单进程的情况,使用了fork就变成了多进程情况了,程序在fork函数执行后就已经分成了两条路线了,只是这两条路线在同时执行。
画图理解:
fork的执行情况

当程序调用fork之后,就有两个二进制代码相同的进程,而且它们都运行到相同的地方,但每个进程都可以开始它们自己的进程,还是上面的代码:

#include <unistd.h>#include <sys/types.h>#include <stdio.h>#include <stdlib.h>int main(){printf("Before: pid is %d\n",getpid());pid_t id = fork();if(id < 0){perror("fork");exit(1);}if(id == 0){//childprintf("After: pid is %d,fork return %d\n",getpid(),id);}else if(id != 0){//parentprintf("After: pid is %d,fork return %d\n",getpid(),id);}return 0;}//打印结果:/*Before: pid is 25514After: pid is 25514,fork return 25515After: pid is 25515,fork return 0*/

这里的Before打印了一变,可是after却打印了两遍。
fork的执行情况

正是有了这种机制,fork之前父进程独自执行,fork之后,父子进程执行流分别执行。注意,fork之后,谁先执行完全由调度器决定。

3.写时拷贝

通常,父子代码共享,父子不再写入时数据是共享的,当任意一方尝试写入,便以写时拷贝的方式各种一份副本。
写时拷贝

4.fork的常规用法

一个父进程希望复制自己,使父子进程同时执行不同的代码片段。例如父进程等待客户端的请求,生成子进程来处理情况。一个进程要执行一个不同的程序,例如子进程从fork返回后,调用exec函数

5.fork调用失败的原因

系统中有太多的进程。实际用户的进程数超过了限制。

点击全文阅读


本文链接:http://zhangshiyu.com/post/177868.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1