当前位置: 首页 > article >正文

进程状态以及两种特殊进程

目录

  • 进程状态
    • 1 具体状态
    • 2 进程状态的意义
    • 3 进程状态实例
      • 3.1 R&S&T认识
      • 3.2 认识Z & 僵尸进程 & 孤儿进程
        • 僵尸进程
        • 孤儿进程

进程状态

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在Linux内核里,进程有时候也叫做任务)。

下面的状态在kernel源代码里定义:

/*
* The task state array is a strange "bitmap" of
* reasons to sleep. Thus "running" is zero, and
* you can test for combinations of others with
* simple bit tests.
*/
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 */
};

1 具体状态

1.1 运行状态

  • R 运行状态(running):

    • 并不意味着进程一定在运行中,它表明进程要么是在运行中,要么在运行队列里。

    • 一个进程处于运行状态,实质上是这个进程已经被放入运行队列run_quene当中,随时可被CPU进行调度。(等待CPU)

1.2 睡眠状态

当我们完成某种任务时,任务条件不具备,需要进程进行某种等待,此时这种状态称为 S 或 D。一个外设可能被多个进程等待,此时这个队列叫做等待队列wait_queue(等待外设)。当“等待成功”,进程将被设为R状态,进入运行队列run_quene

  • S 睡眠状态(sleeping):意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠interruptible sleep),可能会被杀掉。 (浅度睡眠

  • D 磁盘休眠状态(Disk sleep):有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的进程通常会等待IO的结束,进程如果处于D状态,不可被杀掉。(深度睡眠

所谓的进程,在运行的时候,有可能因为运行需要,可能会在不同的队列里。

因此,在同一个队列里,所处的状态不一定是一样的。

我们把,从运行状态的task_struct(run_queue),放到等待队列中,就叫做挂起等待(阻塞)

从等待队列,放到运行队列,被CPU调度就叫做唤醒进程!

1.3 停止状态

  • T 停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行。

  • t (tracing stop):追踪导致的暂停状态(断点之类)。

1.4 死亡状态&僵尸状态

  • X 死亡状态(dead):这个状态只是一个返回状态,不会在任务列表里看到这个状态。
    • 回收进程资源=进程相关的内核数据结构+相关代码和数据
  • Z 僵尸状态(zombie):进入僵死状态,辨别“死亡原因”,即进程退出的信息,系统将此信息保存在task_struct里,供系统或父进程进行读取。

进程的状态信息存在task_struct(PCB)里。

image-20230425224057518

2 进程状态的意义

方便OS快速判断进程,完成特定的功能,比如调度,本质是一种分类。

3 进程状态实例

3.1 R&S&T认识

代码myproc.cc

#include<iostream>
#include<unistd.h>
int main(){
    while(true){
        std::cout << "hello world !" << std::endl;
    }
    return 0;
}

运行并查看进程状态,为S+
image-20230426131457300
查看可执行的kill,并停止目标进程
image-20230426131726464
查看停止后进程状态,为T
image-20230426132236164
使进程继续运行,kill -18,并查看进程状态,此时我们发现,进程状态为S,并且使用ctrl+c不能停止进程了
image-20230426133014414
这是因为此时进程在后台运行,此时需用kill -9(SIGKILL)杀掉进程
image-20230426133320500

  • 前台运行:直接使用 ./myproc
  • 后台运行:使用 ./myproc &,后台进程,可以在当前页面继续执行其他命令

3.2 认识Z & 僵尸进程 & 孤儿进程

僵尸进程

僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵死(尸)进程。

僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。

所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态

首先通过下面这个例子认识一下Z进程。

myproc.cc

#include <iostream>
#include <unistd.h>
int main(){
    
  pid_t id = fork();
    
  if(id == 0){
     //child
    while(true){
      std::cout << "I am child, running !" << std::endl;
      sleep(2);
    }
  }
  else{
    //parent
    std::cout << "father do nothing!\n" << std::endl;
    sleep(50);
  }
  return 0;
}
  • 运行./myproc,使用while :; do ps axj | head -1 && ps ajx | grep myproc | grep -v grep; sleep 1; echo "############################################"; done查看当前进程状态

    image-20230426195030189

  • 使用kill -9杀掉子进程

    image-20230426195207641

    image-20230426195242091

可以看到,因为无回收的操作,子进程成为僵尸进程

父进程如果一直不读取,那子进程就一直处于Z状态,Z状态一直不退出,PCB一直都要维护。

长时间不回收,占用系统资源,而C中定义一个结构体变量,是要在内存的某个位置进行开辟空间,此时僵尸进程的存在也有可能造成内存泄漏

如果父进程先”死“,那么子进程会如何,谁来回收它呢?

孤儿进程

父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?父进程先退出,子进程就称之为“孤儿进程”

孤儿进程被1号init进程领养,由init进程回收。

myproc.cc

#include <iostream>
#include <unistd.h>
int main(){
    
  pid_t id = fork();
    
  if(id == 0){
     //child
    while(true){
      std::cout << "I am child, running !" << std::endl;
      sleep(2);
    }
  }
  else{
    //parent
    std::cout << "father do nothing!\n" << std::endl;
    sleep(10);
    exit(1);
  }
  return 0;
}
  • 开始运行。

    image-20230426200257763

  • 10秒后,父进程结束,子进程依然在。并且进程状态由S+变为S,ppid变为1,称此时的进程为孤儿进程,而”领养孤儿进程“的1号进程通常为操作系统

    image-20230426201059595


http://www.kler.cn/a/15479.html

相关文章:

  • ssm129办公用品管理系统开发与设计+jsp(论文+源码)_kaic
  • el-table中增加校验方法(二)
  • 红外遥控信号解码
  • 蓝桥杯备赛(持续更新)
  • 【Ubuntu24.04】使用服务器
  • HDMI之SBTM
  • Java 网络编程 —— Socket
  • C——Typedef是什么?如何使用?有何便利之处?
  • 下载——安装——使用FinalShell
  • 权威学者、企业CFO荟聚上海国家会计学院,共探「智能会计 价值财务」
  • 30基于非对称纳什谈判的多微网电能共享运行优化策略MATLAB程序
  • 最值得学的编程语言是哪个?
  • 10、Java继承与多态 - 内部内的概念与分类
  • hw xm 的额外symbol汇总
  • 为什么要用虚拟 DOM?
  • Open3D 最小二乘拟合二维直线
  • 智能合约的分层设计浅谈
  • 可视化CNN和特征图
  • Java 中的异常处理机制是什么?如何使用它来处理程序中的异常?(七)
  • 玩转ChatGPT:Auto-GPT项目部署与测评
  • 机器学习实战教程(十):逻辑回归
  • 手把手带你写一份优秀的开发求职简历(四)
  • 亚科转债,鹿山转债上市价格预测
  • Leetcode力扣秋招刷题路-0853
  • 能上网的ChatGPT,会带来什么改变
  • 【信息安全案例】——身份与访问安全(学习笔记)