【Linux】进程状态(+僵尸进程、孤儿进程)

进程状态

查看进程状态的命令:

ps aux 
ps axj 命令
  1. R(running):可执行状态

并不一定正在占有CPU,它表明进程要么是正在运行,要么是在运行队列里。实际上分为running和ready两种状态。

  1. S(task_interruptible):可中断的睡眠状态

处于这个状态的进程因为等待某事件的发生,比如soket连接、信号量而被挂起。

  1. D(task_uninterruptible):不可中断的睡眠状态

进程处于睡眠状态,但是此刻进程是不可中断的。指的并不是CPU不响应外部硬件的中断,而是不响应异步信号

而TASK_UNINTERRUPTIBLE状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程(这个插入的流程可能只存在于内核态,也可能延伸到用户态),于是原有的流程就被中断了。

  1. T(task_stopped or task_traced):暂停状态或跟踪状态

向进程发送一个SIGSTOP信号,它就会因响应该信号而进入TASK_STOPPED状态(除非该进程本身处于TASK_UNINTERRUPTIBLE状态而不响应信号)。(SIGSTOP与SIGKILL信号一样,是非常强制的。不允许用户进程通过signal系列的系统调用重新设置对应的信号处理函数。)

向进程发送一个SIGCONT信号,可以让其从TASK_STOPPED状态恢复到TASK_RUNNING状态。

  1. X(task_dead - exit_dead):退出状态,进程即将被销毁

这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

  1. Z(task_dead - exit_zombie):退出状态,进程成为僵尸状态。

进程在退出的过程中,处于TASK_DEAD状态。

在这个退出过程中,进程占有的所有资源将被回收,除了task_struct结构(以及少数资源)以外。于是进程就只剩下task_struct这么个空壳,故称为僵尸。

fork

一个进程可以通过调用fork函数来创建一个新的进程,即子进程。

进程参数:
在这里插入图片描述

返回值的区别:

  • 子进程返回值0。因为子进程的父进程是可以唯一确定的,通过getpid方法可以获取到父进程id。
  • 父进程返回的是新创建的子进程的ID,因为父进程可以创建多个子进程,没有函数可以获取该线程的所有子线程的所有id。

孤儿进程

孤儿进程就是父进程先于子进程退出。

[root@iz2ze76ybn73dvwmdij06zz ~]# cat guer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>


int main()
{
    pid_t pid = fork();

    if (pid < 0) {
 perror("fork error;");
        exit(1);
    } else if (pid == 0) {
 sleep(5);
        printf ("子进程 : [ pid] = %d , 父进程 [ppid] = %d\n",getpid(),getppid());
        exit(0);

    } else if (pid > 0) {
 printf("我是父线程,我先退出一步~\n");
 exit(0);

    }
  return 0;
}

在这里插入图片描述
父进程退出后,子进程被ID=1的init进程领养了。每当有孤儿进程出现的时候,init进程就会收养它并成为它的父进程。

危害:

孤儿进程会被init进程接管,所以没有危害。

任何一个子进程(init除外)在exit()之后,并非马上就消失掉,而是留下一个称为僵尸进程(Zombie)的数据结构,等待父进程处理。这是每个 子进程在结束时都要经过的阶段。如果子进程在exit()之后,父进程没有来得及处理,这时用ps命令就能看到子进程的状态是“Z”。如果父进程能及时 处理,可能用ps命令就来不及看到子进程的僵尸状态,但这并不等于子进程不经过僵尸状态。 如果父进程在子进程结束之前退出,则子进程将由init接管。init将会以父进程的身份对僵尸状态的子进程进行处理。

Z(ZOMBIE)僵尸进程

正常情况下,子进程是通过父进程创建的,子进程在创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程 到底什么时候结束。

和孤儿进程相反,子进程先行退出,而父进程又没有处理回收释放的子进程的资源,这个时候子进程就成了僵尸进程。

危害

  • 如果进程不调用wait / waitpid的话, 那么保留的那段信息就不会释放,其进程号就会一直被占用,但是系统所能使用的进程号是有限的,如果大量的产生僵死进程,将因为没有可用的进程号而导致系统不能产生新的进程。

处理

  1. 干掉父进程

干掉父进程,让剩下的子进程变成孤儿进程,就会由init接管,并且处理这些进程的资源释放工作。

  1. 父进程调用wait 或 waitpid

特别注意,僵尸进程是不能使用 kill 命令清除掉的。因为 kill 命令只是用来终止进程的,而僵尸进程已经终止

等函数等待子进程结束,这会导致父进程挂起。执行wait()或 waitpid()系统调用,则子进程在终止后会立即把它在进程表中的数据返回给父进程,此时系统会立即删除该进入点。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页