IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux中fork函数详解(附图解) -> 正文阅读

[系统运维]Linux中fork函数详解(附图解)

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

#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 Start
	pid_t pid;
	pid = fork();
	if (pid > 0)
	{
		printf("parent running\n");
		while (1)
		{
			sleep(1);
		}
	}
	else if (pid == 0)
	{
		//Child Start
		printf("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!

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章           查看所有文章
加:2022-05-24 18:35:01  更:2022-05-24 18:38:02 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:49:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码