1

0. 同系列索引

  1. 进程与进程组
  2. 各种不同的进程
  3. 一个进程的演变

1. 进程组

具体的介绍,请参考 进程和进程组的概念

clipboard.png

比如 ngixn php-fpm 终止了主进程,关联的子进程就都关闭了

2. 前台进程 和 后台进程

2.1 二者的区别

前台进程,就是运行在终端当前窗口的进程组

clipboard.png

clipboard.png

2.2 进程的前后台切换

clipboard.png

2.3 查看后台进程

clipboard.png

后台命令放到前台

clipboard.png

3. 守护进程

3.1 什么是守护进程

clipboard.png

文字的描述或许有点抽象,我们来看下一个服务器中的守护进程

3.2 守护进程

clipboard.png

从上图可以看出 我们日常的php-fpm服务,一直在后台运行守护,等待分配运行。
以及我们的swoole服务。

还有我们的内核服务,一直在守护者操作系统的正常运行。

clipboard.png

PS : -1 就是没有和任何终端建立关联,一般是守护进程。 系统服务进程一般名称都会包含d

3.3 守护进程的应用

clipboard.png

关于对比,守护进程和后台进程的区别

  1. 守护进程已经完全脱离终端的控制
  2. 后台进程没有完全脱离,他的一些输出信息会输出到终端
  3. 关闭终端时,后台进程会随之终止,而守护进程会继续进行。 比如nginx,或者系统进程
  4. 守护进程没有独立的会话,文件描述符,工作目录。而后台进程是继承父进程的

3.4 守护进程的启动

clipboard.png

这些一般在系统开机的时候启动

4. 僵死进程

4.1 父进程和子进程的关联

在介绍僵死进程之前,我们再重新描述下父进程和子进程之间的关联。
父进程---(fork)----子进程:执行任务
父进程---(wait)----子进程:释放资源

概括而言:

  • 父进程使用fork创建子进程,在调度器调度下调度运行不同的子进程
  • 子进程运行结束后退出(父进程wait之前),内核会自动释放相关的资源

    • 释放占用的内存,打开的文件
    • 仍然保留一定的信息:进程ID,退出状态,运行时间。(子进程独享的一些状态)
  • 父进程调用 wait 获取子进程的退出状态,释放最后的资源。

所以如果子进程退出,但是父进程没有调用wait,子进程的进程ID 等特殊资源不会被立即释放,这些就变成了僵死进程。

4.2 僵死进程

僵死进程 : 子进程 exit 退出。父进程没有调用 wait 获取子进程状态,那么子进程的相关资源仍然保存在系统中

僵死进程会占用PID等资源,如果系统中存在大量的僵死进程,会影响fork子进程。

PS :想想一下,同时运行多个脚本,子进程退出,但是没有释放PID,进程资源优先。新来的任务就无法fork出新的子进程ID
当然,系统会做一个清理的工作。

4.3 一个demo

clipboard.png

5. 孤儿进程

5.1 什么是孤儿进程

孤儿:通俗易懂,没有父亲就是孤儿。
同样的孤儿进程,就是找不到父进程的子进程。

如果子进程在执行过程中,父进程先行退出,子进程就会托管给了init进程,那么该子进程就是一个孤儿进程。

5.2 一个孤儿进程的demo

clipboard.png

通过休眠时间控制,在子进程执行期间,父进程提前退出

查看一下输出结果

clipboard.png

5.3 分析一下托管父进程

上图中我们可以看到,在父进程退出时,子进程会新找一个父亲当做父进程。 这个父进程的PID: 是 1637:upstart进程

clipboard.png

我们再深入研究一下

clipboard.png

发现很多进程托管在 upstart进程 上

不同的系统,接管的父进程不一样,是有具体的0号进程演变有关。

下面看下在虚拟终端页面和控制台页面的接管父进程

虚拟终端

clipboard.png

图形界面:

clipboard.png

具体为什么这种差异,需要从 1号进程 的产出具体说明。

6. 0号进程和1号进程

6.1 一切的起源:0号进程

clipboard.png

关于1号进程和2号进程,后续再慢慢解释

clipboard.png

从上图可以知道,0号进程是一切的开始,他伴随着开机启动,他是唯一一个不是由fork产生的进程。

在内核启动的过程中,会通过 start_kernel 依次初始化 内核的各种模型,组件,进程等。

下图:是 start_kernel 主要工作概览

clipboard.png

clipboard.png

初始化完 0号进程 idle 之后 start_kernel 里面会完成很多初始化工作。其中最后一步包括 :rest_init

rest_init 会调用 init_task
init_task 调用 kernel_thread
kernel_thread 会创建 init 进程 和 ktheadd 内核线程

init_task : 最终会演变成 0号进程 idle

6.2 从0到1

关于用户进程的创建,请参考 一个进程的演变

100. 致敬

如有不详,请参考王老师的精彩讲解
学习过程中,获得了极大的满足感,把之前的一些东西串联了起来。十分感谢 王利涛老师
在此表示感谢。
PS:本文中所有的资源和图片均来自视频中


天真真不知路漫漫
70 声望6 粉丝

1