除了运行、休眠…进程居然还有僵尸、孤儿状态

除了,运行,休眠,进程,居然,还有,僵尸,孤儿,状态 · 浏览次数 : 106

小编点评

## 华为云新鲜技术简介 **1. 华为云新鲜技术的定义** 华为云新鲜技术是指华为云提供一些新鲜的技术,例如华为云智能、华为云数据、华为云计算等。这些技术可以让用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据设备、华为云计算设备等。 **2. 华为云新鲜技术的特点** * **华为云智能:**华为云智能是华为云提供一些智能服务的名称,例如华为云智能设备、华为云数据智能等。华为云智能可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据设备、华为云计算设备等。 * **华为云数据:**华为云数据是华为云提供一些数据服务的名称,例如华为云智能数据、华为云数据存储等。华为云数据可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 * **华为云计算:**华为云计算是华为云提供一些计算服务的名称,例如华为云智能计算、华为云数据计算等。华为云计算可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 **3. 华为云新鲜技术的优势** * **华为云智能:**华为云智能可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据设备、华为云计算设备等。 * **华为云数据:**华为云数据可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 * **华为云计算:**华为云计算可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 **4. 华为云新鲜技术的应用** 华为云新鲜技术可以应用于许多不同的场景,例如: * **华为云智能设备:**华为云智能设备可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据设备、华为云计算设备等。 * **华为云数据存储:**华为云数据存储可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 * **华为云计算:**华为云计算可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据存储等。 **5. 总结** 华为云新鲜技术是华为云提供一些新鲜的技术,可以帮助用户在华为云上创建一些新的设备,例如华为云智能设备、华为云数据设备、华为云计算设备等。华为云新鲜技术可以应用于许多不同的场景,例如华为云智能设备、华为云数据存储等。

正文

摘要:本章我们将认识几种进程状态——运行状态、休眠状态、暂停状态、退出状态等。还要介绍两种具有惨烈身世的僵尸进程与孤儿进程~

本文分享自华为云社区《僵尸进程?孤儿进程?为什么他有如此惨烈的身世...》,作者: 花想云 。

认识进程状态

Linux中进程状态一般有:

  • R(运行状态):并不意外着真正的在运行(指正在被CPU调度);
  • S(休眠状态):进程在等待获取某种资源,此状态还被称为可中断休眠;
  • D(磁盘休眠状态):在这个状态的进程也是在休眠,但是不可被中断,因此又称过该状态为不可中断休眠;
  • T(暂停状态):可以通过发送 SIGSTOP 信号给进程来停止进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。
  • X(死亡状态):这个状态只是一个返回状态,你不会在任务列表里看到这个状态;
  • Z(僵尸状态):当一个子进程没有被父进程“回收”,该进程就会处于僵尸状态;

下面为这些状态在kernel源代码中的定义:

static const char * const task_state_array[] = {
“R (running)”, // 0
“S (sleeping)”, // 1
“D (disk sleep)”, // 2
“T (stopped)”, // 4
“t (tracing stop)”, // 8
“X (dead)”, // 16
“Z(zombie)”, // 32
};

如何查看进程状态

  • 输入指令:
ps axj | head -n1 && ps axj | grep myprocess | grep -v grep

接下来我们就依次来看各种状态是什么模样吧~

R状态

引例

当你在电脑上同时运行很多程序,例如你敲代码的时候,还听着某个软件播放的歌曲,或者在浏览器之间来回切换。请问此时这些所有的应用都在CPU运行吗?

答案是,并不是这样的。

在CPU进行工作的时候,会存在一个进程运行的队列。队列维护的内容是一个个task_struct结构体的指针(上一章中讲到了task_struct为进程描述符)。在该队列中维护的进程都处于R状态,且等着被CPU所调度。

如何观察

写下一段简单的代码:

#include<stdio.h>
#include<unistd.h>
int main()
{
 while(1)
 {
 printf("hello myprocess\n");
 }
 return 0;
}

在运行该程序之后,查看该进程的状态如图所示:

  • 问题又来了,为什么在该程序执行时,并没有看到所谓的R状态呢?
  • 答案是,由于CPU运算速度太快了,我们基本很难看到R状态。该进程死循环的在屏幕上打印hello myprocess。我们都知道此时的屏幕是一种外设,而CPU的计算速度相比较外设的访问速度根本不在一个量级。所以,该进程死循环的在屏幕上打印内容,有99.9%的时间都在访问外设,剩下的时间是CPU在做计算。在进程访问外设的时候,CPU并不会傻傻的原地等待,而是转头却做别的事,当该进程访问外设成功后,CPU再对它进行调度。

那么有什么办法等看到R状态呢?我们将上面的代码略作修改:

#include<stdio.h>
#include<unistd.h>
int main()
{
 while(1)
 {
 //printf("hello myprocess\n");
 }
 return 0;
}

如上图所示,当我们不再访问外设,而是只不停地做重复的运算,此时CPU会一直被调度,就能看到R状态了。

S状态与D状态

S状态

S状态称为休眠状态。一个进程好端端地为什么要休眠呢?难道是因为运行太久累到了吗?当然不是这样。休眠状态本质是一种阻塞。

  • 阻塞:进程因为等待某种资源就绪而表现出的不推进的状态。

例如,当一个进程运行到一半,需要从磁盘上获取很大的一块数据,那么就要花费较久的时间。此时OS的处理方式是,让该进程继续等待它要的数据,但是要求你不能在等待资源的时候还占用着CPU,于是该进程就被OS安排到某个地方进行等待,这时该进程就处于S状态。

如何观察

#include<stdio.h>
#include<unistd.h>
int main()
{
 while(1)
 {
 int n = 0;
 scanf("%d",&n);
 printf("%d\n",n);
 }
 return 0;
}

如上图所示,当进程等待用户从键盘上输入的数据时,它就处于睡眠状态。

D状态

D状态也是一种休眠状态,但是它又有个名字叫做磁盘休眠状态或者不可中断休眠。那么如何看待S状态与D状态的区别呢?

首先我们得清楚一般什么情况下进程会发生中断。当一个进程偷偷地地干一些坏事,此时用户想停止该进程,那就要向该进程发送一个中断信号,该进程就被“杀”掉了。

在一些情况下,不需要用户自己动手,OS自己就能“杀”掉某些进程。例如,当内存资源非常紧张甚至危险到了整个系统的安全时,OS就会“杀”掉一些不太重要的进程。

就比如某个进程因为在等待数据而进入休眠状态,此时被OS发现了,内存这么紧张你还在这睡懒觉?叉出去!好嘛,进程被叉出去了。此时数据被读到一半,结果当事人没了。这些数据只能被舍弃,不然谁找到刚刚那个进程投胎之后还能不能找到“我“。

这些被舍弃的数据若是一些无关紧要的数据也就罢了,丢就丢了。但若是什么机密文件那岂不是坏了大事了?所以,为了避免将某些不能中断的进程被OS误杀掉了,可让该进程处于不可被中断休眠状态即D状态。此时该进程休眠时终于不怕被打扰了,但是,各退一步,我换个地方睡,不然我怕你急眼。于是该进程休眠时,就在相对宽阔的磁盘当中去休眠了。

T状态

T状态称为停止状态,非常好理解,就是让某个进程暂停一下。例如在调试时,我们设置了几个断点。当进程在该断点处停下来时,该进程就处于暂停状态。

如何观察

方法一

#include<stdio.h> 
#include<unistd.h>
int main() 
{ 
 while(1) 
 { 
 //printf("hello myprocess\n"); 
 int n = 0; 
 scanf("%d",&n); printf("%d\n",n); 
 }
 return 0;
}

当我们在第9行打上断点并运行后,程序停到了断点的位置。此时查看进程状态如下图所示:

注意:t也是一种暂停状态。有时候也被叫做追踪状态。

方法二

我们可以通过给进程发送暂停的信号使进程进入暂停状态。编辑如下代码:

#include<stdio.h> 
#include<unistd.h>
int main() 
{ 
 while(1) 
 { 
 printf("hello myprocess\n"); 
 }
 return 0;
}

当程序开始运行后,此时向进程发送暂停的信号:

$ kill -19 (进程PID)

此外,我们还可以发送继续的信号让该进程继续执行:

$ kill -18 (进程PID)

注意

进程继续在运行了。但是我们发现有一个地方好像和之前不一样了,S后面是不是一直有一个+号来着?我们也不知道+是干嘛的,只知道他现在好像消失了。

  • “+” 代表在前台运行,没有”+“表示在后台运行;

之前我们在终止一个程序时,习惯使用Ctrl + c ,但是现在好像对于后台在运行的进程失效了,此时我们需要掌握一条新的指令来”杀掉“进程:

$ kill -9 (进程PID)

或者,

$ kill -9 (进程PID)

X状态与Z状态

  • X状态为退出状态是一个瞬时状态不易观察,暂且认为它不重要;
  • Z状态被称为僵尸状态。顾名思义,一个进程死了(退出了)但没有”收尸“,就成了”僵尸“。具体一点,当一个进程退出时如果它的父进程没有读取到该进程退出时返回的退出状态码,该进程就会变成僵尸进程。

概念有点多,先来理一理。首先什么是退出状态码?在一段C语言程序中,我们经常要在main函数结束时写一句代码——return 0; 。这个0就是退出状态码,但并不仅仅是0,还可以是1,2,3…

如何看到僵尸进程?

接下来我们就写一段代码看看僵尸进程:

#include<stdio.h> 
#include<unistd.h>
int main() 
{
 pid_t id = fork();
 if(id == 0)
 {
 while(1)
 {
 printf("我是子进程,我在运行,pid:%d,ppid:%d\n",getpid(),getppid());
 sleep(1);
 }
 }
 else if(id > 0) 
 {
 while(1)
 {
 printf("我是父进程,我在运行,pid:%d,ppid:%d\n",getpid(),getppid());
 sleep(1);
 }
 }
 return 0;
}

当我们运行程序后,能看到程序正常的在运行;

此时当我们执行指令将子进程”杀“掉,子进程就会变成僵尸进程;

$ kill -9 (子进程PID)

其中我们能看到一个英文单词——defunct就是僵尸的意思。

僵尸进程的危害

  • 维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(即PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护。
  • 一个父进程创建了很多子进程,就是不回收,就会造成内存资源的浪费。因为数据结构对象本身就要占用内存。

僵尸进程是有危害的,当然我们也可以避免它,这就需要在下一章节中提到了。

孤儿进程

当父进程活着,子进程提前挂掉,容易造成僵尸进程。那如果父进程提前挂掉,子进程又该何去何存呢?这就是我们接下来要讲的孤儿进程了。

如何看到孤儿进程

编辑如下代码:

#include<stdio.h> 
#include<unistd.h>
int main() 
{
 pid_t id = fork();
 if(id == 0)
 {
 while(1)
 {
 printf("我是子进程,我在运行,pid:%d,ppid:%d\n",getpid(),getppid());
 sleep(1);
 }
 }
 else if(id > 0) 
 {
 while(1)
 {
 printf("我是父进程,我在运行,pid:%d,ppid:%d\n",getpid(),getppid());
 sleep(1);
 }
 }
 return 0;
}

运行该程序,我们使用kill命令”杀“掉父进程,此时再来查看进程信息:

如上图所示,子进程发生了两个变化。一是子进程的PPID,二是子进程变为在后台运行了。

如何理解

当子进程的父进程挂掉之后,子进程会被1号进程领养。该进程也被称为孤儿进程。

  • 那么为什么要进行领养呢?

答案是,找一个人为自己收尸。不然当哪一天自己突然挂掉,没人为自己收尸那么就会变成为祸人间的僵尸进程了。

 

点击关注,第一时间了解华为云新鲜技术~

与除了运行、休眠…进程居然还有僵尸、孤儿状态相似的内容:

除了运行、休眠…进程居然还有僵尸、孤儿状态

摘要:本章我们将认识几种进程状态——运行状态、休眠状态、暂停状态、退出状态等。还要介绍两种具有惨烈身世的僵尸进程与孤儿进程~ 本文分享自华为云社区《僵尸进程?孤儿进程?为什么他有如此惨烈的身世...》,作者: 花想云 。 认识进程状态 Linux中进程状态一般有: R(运行状态):并不意外着真正的在

百度飞桨(PaddlePaddle)- 张量(Tensor)

张量(Tensor)、标量(scalar)、向量(vector)、矩阵(matrix) 飞桨 使用张量(Tensor) 来表示神经网络中传递的数据,Tensor 可以理解为多维数组,类似于 Numpy 数组(ndarray) 的概念。与 Numpy 数组相比,Tensor 除了支持运行在 CPU 上

[转帖]指定运行时动态库位置的三种方式

https://blog.csdn.net/gx_1983/article/details/78352457 指定运行时动态库位置的三种方式 在Linux 中,动态库的搜索路径除了默认的搜索路径外,还可通过三种方法来指定:方法一:在配置文件/etc/ld.so.conf中指定动态库搜索路径;方法二:

[转帖]人人都应该知道的CPU缓存运行效率

https://zhuanlan.zhihu.com/p/628017496 提到CPU性能,大部分同学想到的都是CPU利用率,这个指标确实应该首先被关注。但是除了利用率之外,还有很容易被人忽视的指标,就是指令的运行效率。如果运行效率不高,那CPU利用率再忙也都是瞎忙,产出并不高。 这就好比人,每天

[转帖]JVM——内存区域:运行时数据区域详解

https://www.jianshu.com/p/cded765cfd1b 关注:CodingTechWork,一起学习进步。 引言 我们经常会被问到一个问题是Java和C++有何区别?我们除了能回答一个是面向对象、一个是面向过程编程以外,我们还会从底层内存管理和垃圾收集方面作出比较。 对于C++

Junit4 一直处于运行中的排查过程

新买了一个Macbook Pro . 之前的工程搬家过来, 这天要跑个单元测试。 发现Junit4 一直处于运行中。没有错误信息,没有用例执行结果。遂开始排查原因。 这里插一句,苹果芯片的Mbp还是很好用的,除了性能够用之外,最主要是安静+不热。 这对比我之前的i7版本的真是太明显了。 之前的i7在

批处理及有状态等应用类型在 K8S 上应该如何配置?

众所周知, Kubernetes(K8S)更适合运行无状态应用, 但是除了无状态应用. 我们还会有很多其他应用类型, 如: 有状态应用, 批处理, 监控代理(每台主机上都得跑), 更复杂的应用(如:hadoop 生态...). 那么这些应用可以在 K8S 上运行么? 如何配置? 其实, K8S 针对

[转帖]Java实战之OutOfMemoryError异常问题及解决方法

https://www.jb51.net/article/244872.htm + 目录 在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError (下文称OOM)异常的可能。本篇主要结合着【深入理解Java虚拟机】一书当中整理了本篇博客

[转帖]TiDB 查询优化及调优系列(三)慢查询诊断监控及排查

https://zhuanlan.zhihu.com/p/509984029 本章节介绍如何利用 TiDB 提供的系统监控诊断工具,对运行负载中的查询进行排查和诊断。除了 上一章节介绍的通过 EXPLAIN 语句来查看诊断查询计划问题 外,本章节主要会介绍通过 TiDB Slow Query 慢查询

是时候,升级你的 Windows 了「GitHub 热点速览」

不知道多少小伙伴用着 Windows 操作系统,可能会有一个烦恼是有时候操作系统过慢,因为众多拖慢 Windows 系统的组件。Atlas 作为一个修改版的 Windows 系统,能极大提高操作系统运行效率。说到升级,除了 Atlas 之外,还有主打内存安全的 sudo 升级版 sudo-rs,以及