【Linux初阶】fork进程创建 & 进程终止 & 进程等待

文章详细介绍了Linux中进程的创建,包括fork函数的原理、返回值和常规用法,以及进程终止的各种方式如exit和_return。接着讨论了进程等待的wait和waitpid函数,以及如何获取子进程的退出状态。最后提到了阻塞等待与非阻塞等待的区别和应用场景。
摘要由CSDN通过智能技术生成

 🌟hello,各位读者大大们你们好呀🌟

🍭🍭系列专栏:【Linux初阶】

✒️✒️本篇内容:fork进程创建,理解fork返回值和常规用法,进程终止(退出码、退出场景、退出方法、exit),进程等待(wait、waitpid),阻塞等待和非阻塞等待

🚢🚢作者简介:本科在读,计算机海洋的新进船长一枚,请多多指教( •̀֊•́ ) ̖́-

目录

一、进程创建

1.fork函数初识

2.fork返回值

(1)如何理解 fork函数有两个返回值

(2)如何理解 fork返回后,给父进程返回子进程的 pid,给子进程返回 0?

(3)如何理解同一个 id值,会返回两个不同的值,让 if 和 else if 同时执行

(4)理解写时拷贝

3.fork常规用法

4.fork调用失败的原因

二、进程终止

1.进程退出码

2.进程退出场景

3.进程常见退出方法

4.exit函数

5._exit函数

6.return

三.进程等待

1.wait方法

2.waitpid方法

3.获取子进程status

4.进程等待总结

四、再谈进程退出

五、阻塞等待 vs 非阻塞等待

1.阻塞等待应用示例 

2.非阻塞等待应用示例


一、进程创建

1.fork函数初识

在linux中fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。

#include <unistd.h>
pid_t fork(void);
返回值:子进程中返回0,父进程返回子进程id,出错返回-1

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

  • 分配新的内存块和内核数据结构给子进程
  • 将父进程部分数据结构内容拷贝至子进程
  • 添加子进程到系统进程列表当中
  • fork返回,开始调度器调度

如下图所示,调用fork后,将生成一个新的进程

 代码示例如下

int main(void)
{
	pid_t pid;
	printf("Before: pid is %d\n", getpid());
	if ((pid = fork()) == -1)perror("fork()"), exit(1);
	printf("After:pid is %d, fork return %d\n", getpid(), pid);
	sleep(1);
	return 0;
}

运行结果:
[root@localhost linux]# . / a.out
Before : pid is 43676
After : pid is 43676, fork return 43677
After : pid is 43677, fork return 0

这里看到了三行运行结果,一行before,两行after。进程43676先打印before消息,然后它又打印after。另一个after消息是43677打印的。注意到进程43677没有打印before,为什么呢?如下图所示

所以, fork之前父进程独立执行,fork之后,父子两个执行流分别执行
 

我们可以看到上述代码中并没有对父子进程进行条件限制,那么在程序运行起来时,在 fork之后,会先执行父进程还是子进程呢?实际上,fork之后,谁先执行完全由调度器决定。 

2.fork返回值

(1)如何理解 fork函数有两个返回值

首先,我们必须要知道 fork函数是操作系统为我们提供的,也就是说,fork操作是在操作系统内实现的

接下来,我们一起来看下 fork函数内部的结构,然后思考一个问题:在代码在 return之前,内部的核心代码实现完了吗?

答案是,实现完了!也就是说,子进程早在 return前就创建好了,并且可能已经在 OS的运行队列中,准备被调度了。对应的,当代码运行到 return时,会有父进程、子进程两个进程各自执行return

(2)如何理解 fork返回后,给父进程返回子进程的 pid,给子进程返回 0?

因为一个父亲的孩子可以有很多个,可是每个孩子都只有一个父亲。也就是说,孩子找父亲是具有唯一性的。以此类推,子进程 fork之后,不需要父进程的 id值,因为父进程具有唯一性。而父进程 fork之后需要对应子进程的 id,因为该父进程可能不止一个子进程,它需要对应的子进程 id做标识

(3)如何理解同一个 id值,会返回两个不同的值,让 if 和 else if 同时执行

返回的本质:就是写入。我们不知道父子进程谁先返回,谁先返回,谁就先写入 id值。由于进程具有独立性,进程在执行 fork相应代码时,会在操作系统内部进行写时拷贝,使 fork对应的进程可以返回两个不同的值,再让对应的父子进程根据自己返回的 id,去执行 if 或 else if 中的代码内容。

(4)理解写时拷贝

通常情况下,父子代码共享,父子进程在不写入(不修改共享部分的数据)时,对应的数据也是共享的。当任意一方试图写入,操作系统便会以写时拷贝的方式,给需要修改的一方在物理内存中开辟一块新空间,将原来的数据拷贝到新空间中,再对新空间中的数据做修改。具体见下图: 

———— 我是一条知识分割线 ————

3.fork常规用法

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

4.fork调用失败的原因

  • 系统中有太多的进程
  • 实际用户的进程数超过了限制(一个用户可以创建的进程是有限制的)


二、进程终止

1.进程退出码

这里给大家讲解一下进程退出码,我们知道写代码是为了完成某件事情,那我们如何知道这件事完成的怎么样呢?我们可以通过进程退出码来了解。

进程在退出时,会有对应的退出码,标定进程执行的结果是否正确

退出码的意义

评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值