我们先来看个代码,判断一下这个代码的输出结果会是什么样的,先不要去看运行结果,判断好后再去看看是否和你的预期结果一致。

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>int main(void)
{pid_t pid;pid = fork();printf("xxxxxxxxxx\n");while (1) {sleep(1);}return 0;
}

———————————————————————————————————————————

运行结果:

xxxxxxxxxx

xxxxxxxxxx

是不是和你预想的结果不太一样呢?为什么会是输出两遍呢?这是什么原理呢?

抱着这样的问题,让我们来研究一下fork函数的奥秘吧。

fork函数

功能:创建一个与原来进程几乎完全相同的进程

这也就代表着,父进程可通过调用该函数创建一个子进程,两个进程可以做完全相同的事

返回值:pid_t类型的变量,也就是进程id类型的变量

这里有个非常让人惊讶的地方,fork函数的返回值是2个!!!

想想自己学了那么久的编程,好像没有返回值是两个的函数啊。别慌,接着往下看

我们来对父进程通过fork函数创建子进程的过程做个具体的说明,上图!

在上述这个图中,当调用fork函数时,操作系统会从用户态切换回内核态来进行进程的创建,会调用fork函数中的_CREATE函数和_CLONE函数。

首先调用_CREATE函数,子进程进行虚拟地址申请,在子进程的内核空间中进行不完全拷贝,为什么是不完全拷贝呢?就像父亲和儿子的关系一样,你可以和你爸爸的民族,籍贯所在地一样,但你不能和你爸的年龄,身份证号都一样吧。PCB作为每个进程的唯一标识符,就像每个人的身份证一样,是不可能完全一样的,所以这个地方时不完全拷贝,如pid就需要自己生成。这个地方的子进程是新生态。

之后调用_CLONE函数,向父进程拷贝必要资源,子进程的用户空间进行完全拷贝,子进程继承所有父进程资源,如临时数据堆栈拷贝,代码完全拷贝。

这个时候就有善于思考的同学会发现,并提出以下问题:

诶诶诶,你这父进程创建一个子进程,你这子进程把你的代码完全拷贝走了。

  • 那子进程不是把fork函数也拷贝走了吗?
  • 那子进程不也可以通过fork函数创建孙线程了吗?
  • 那你这不是子又生孙,孙又生子吗?
  • 那你这不无限创造进程了吗?
  • 那为什么上面的代码的运行结果只有两个输出?

考虑的非常好啊,这也是我们下面要讲的问题

讲解完父进程如何通过fork函数创建子进程,接下来我们就要讲解父子进程如何执行fork函数

上图!

其实大体来说,我们可以将fork函数分为三步

  1. 调用_CREATE函数,也就是进程创建部分
  2. 调用_CLONE函数,也就是资源拷贝部分
  3. 进程创建成功,return 0;     失败,return -1:

前2步也就是父进程通过fork函数创建子进程的步骤,在执行完_CLONE函数后,fork函数会有第一次返回,子进程的pid会返回给父进程。

要注意的是,在第3步中,fork函数不是由父进程来执行,而是由子进程来执行,当父进程执行完_CLONE函数后,子进程会执行fork函数的剩余部分,执行最后这个语句,fork函数就会有第二次返回,如果成功就返回0,失败就返回-1。

我们就可以总结得出,父子进程都执行fork函数,但执行不同的代码段,获取不同的返回值。所以fork函数的返回值情况如下:

父进程调用fork,返回子线程pid(>0)

子进程调用fork,子进程返回0,调用失败的话就返回-1

这也就说明了fork函数的返回值是2个

可以通过下面的代码来验证该过程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>int main(void)
{//Parent Startpid_t pid;pid = fork();if (pid > 0){printf("parent running\n");while (1){sleep(1);}}else if (pid == 0){//Child Startprintf("Child Running\n");while (1){sleep(1);}//Child End}else{perror("fork call failed\n");}while (1){sleep(1);}return 0;
}
//Parent End

运行结果:

parent running

Child Running

另外和大家说一个小知识点

整个Linux操作系统都是由父子进程结构构成

每个进程都有创建者,也就是父进程,但是有一个进程例外,也就是init进程

init进程(0 or 1),init进程是系统启动初始化后的第一个进程

今天的学习记录到此结束啦,咱们下篇文章见,ByeBye!

Linux中fork函数详解(附图解与代码实现)相关推荐

  1. Linux中fork()函数详解

    Linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  2. linux中fork函数详解,fork() 函数详解

    fork() 函数是 linux/unix 下一种特别的创建子进程的函数,它不同与 Windows,这个函数在执行成功后会有两个返回值,一个返回值==0代表创建了子进程,一个返回值大于0代表还是当前程 ...

  3. Linux中fork函数详解

     一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程, 也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不 ...

  4. linux 中 sigaction 函数详解

    linux 中 sigaction 函数详解 一.函数原型 sigaction 函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作) int sigaction(int signum, ...

  5. Linux中execl函数详解与日常应用(附图解与代码实现)

    目录 execl函数 exec函数族的日常应用 1.Linux中第一个终端的创建 2.终端下.c文件的执行 exec其实并不是一个函数,而是由六个以exec开头的函数所构成的一个函数族,如下图所示 e ...

  6. linux中 fopen函数,详解C语言中的fopen()函数和fdopen()函数

    C语言fopen()函数:打开一个文件并返回文件指针头文件: #include fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为: FILE * fopen(const char * ...

  7. linux中sigaction函数详解

    一.函数原型:sigaction函数的功能是检查或修改与指定信号相关联的处理动作(可同时两种操作) int sigaction(int signum, const struct sigaction * ...

  8. Linux中ftok函数详解

    在ipc通信中 system V 模式的ipc通信中都需要一个key值来生成对应的ID,那么key是如何生成的呢? 通过函数ftok生成 #include <sys/types.h>#in ...

  9. linux中open函数详解

    1.open函数 包含头文件 #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> ope ...

  10. linux中write函数详解

    1.write函数 头文件#include <unistd.h> 三个参数 函数说明:write()会把参数buf所指的内存写入count个字节到参数fd所指的文件内. 返回值:如果顺利w ...

最新文章

  1. jQuery.width()和jQuery.css('width')的区别
  2. 2020届 AAAI Fellow名单新鲜出炉!!!深度学习三巨头终于齐聚
  3. 窗口!窗口!- Windows程序设计(SDK)003
  4. SCI论文写作--工科学生如何入门搞科研和写作
  5. java 将对象转_如何将Java对象转换为C对象?
  6. 7怎么把中文改为英文_windows10系统英文版本,如何更改为中文版本
  7. 我们终于可以把 bug 留给子孙后代了
  8. 升级步骤linux_开发人员福音,在win10系统上安装linux子系统
  9. [JS调用]automation服务器不能创建对象
  10. java8与hibernate_如何在JPA和Hibernate中使用Java 8 LocalDateTime
  11. 网上书店动态网页设计
  12. 怎样知道android的手机号码,怎么知道自己的手机号
  13. 数值积分方法的总结(从简单梯形积分到龙贝格积分、自适应积分、高斯积分等)
  14. 汉诺塔递归算法(Python编程)
  15. Android 6.0 运行时权限管理最佳实践
  16. golang和经济学相关资料学习,还不错,果然B站是个学习的好地方。
  17. linux中的find查找文件或者目录、locate快速定位文件路径
  18. US-016超声波测距模块
  19. JS-关于原型与原型链这件事
  20. 关于pip install numpy

热门文章

  1. 正点原子STM32学习笔记——MPU6050介绍
  2. 多组测试数据01字典树「模板」
  3. python安装win32com模块
  4. hitool java_Hitool打开出现failed to create the java virtual machine
  5. 点击谷歌浏览器安装包没有反应
  6. FinePrint双面打印设置
  7. 整理了个软件需求规格说明书模板
  8. ECSHOP 大商创 对接易支付接口
  9. U8修改销售订单模板
  10. tongweb自动部署_将web应用迁到TongWeb