Linux进程状态以及僵尸进程于孤儿进程的产生


在了解了进程的基本概念以及进程的创建等概念以后,接下来我们需要了解进程的状态。那么什么是进程状态呢?简单的说进程状态就是把一个进程在不同的时间划分为不同的状态。它描述了一个进程在什么时间做什么样的事情。
一般情况下进程有三种状态,就绪,运行,阻塞。

状态名称 描述
就绪 进程已经具备运行条件,但是CPU还没有分配过来,拿到时间片就可以运行
执行 进程占用CPU,并在CPU上运行
阻塞 进程因等待某件事发生而暂时不能运行(如:I/O请求)

三种状态的转换关系如下图:
在这里插入图片描述

Linux下的进程状态

状态名称 描述
运行 正在运行或者拿到时间片就能运行,并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里
可中断休眠 意味着进程在等待事件完成
不可中断休眠 在这个状态的进程通常会等待I/O的结束
停止 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可以通过发送 SIGCONT 信号让进程继续运行
死亡状态 这个状态只是一个返回状态,你不会在任务列表里看到这个状态

通过系统调用fork()创建子进程

通过fork()创建子进程,以复制进程的方式创建一个子进程,代码共享,但数据独有。
代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    
    
 int ret = fork();
 printf("hello proc : %d!, ret: %d\n", getpid(), ret);
 sleep(1);
 return 0;
}

fork()函数,对于父进程返回的是子进程的pid是大于零的,对于子进程来说返回值是0;可以通过返回值对父子进程进行分辨;f返回值小于0表示创建失败,大于0为父进程,等于0为子进程。

代码:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
    
    
 int ret = fork();
 if(ret < 0){
    
    
 perror("fork");
 return 1;
 }
 else if(ret == 0){
    
     //child
 printf("I am child : %d!, ret: %d\n", getpid(), ret);
 }else{
    
     //father
 printf("I am father : %d!, ret: %d\n", getpid(), ret);
 }
 sleep(1);
 return 0;
}

僵尸进程

僵尸状态:是一种特殊的状态,指一个进程退出了但是资源没有完全被释放的状态
僵尸进程:指使用fork创建子进程后,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。即处于僵尸状态的进程。
例子:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>

int main()
{
    
    
  pid_t pid = fork();
  if (pid < 0)
  {
    
    
    perror("fork");
    return 1;
  }
  else if (pid == 0)
  {
    
    
    //创建子进程成功
    printf ("我是子进程,我即将退出\n");
    exit(0);
  }
  else
  {
    
    
    printf("我是父进程,我将睡眠30秒\n");
    sleep(30);
  }
  printf(" 父进程退出\n");
  return 0;
}

使用psps aux | grep testJiangshi 命令查看进程状态

在这里插入图片描述

僵尸进程的危害

因为子进程要告诉父进程,父进程交给子进程的任务完成得怎么样了,所以进程的退出状态必须被维持下去。可父进程一直不读取,那子进程就会一直处于僵尸状态。而维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,因为Z(僵尸)状态一直不退出,PCB就一直都需要维护,如果一个子进程创建了许多子进程,而不回收,就会造成内存资源的浪费。(就和电影中的僵尸一样,已经死亡,但是尸体仍然存在,如果“僵尸”越来越多,又无法销毁,就会把有限的空间完全占满)。

孤儿进程

孤儿进程:和僵尸进程产生的过程相反,孤儿进程是指父进程先于子进程退出,子进程成为孤儿进程运行在后台,父进程成为1号进程(孤儿进程退出不会成为僵尸进程,因为它会被1号进程直接处理)
代码:

#include <stdio.h>
#include <unistd.h>
#include <error.h>
#include <stdlib.h>

int main()
 {
    
    

  pid_t pid = fork();
   if(pid < 0)
   {
    
    
     // 创建失败
     perror("fork");
   }
   else if(0 == pid)
   {
    
    
     //子进程
     printf("我是子进程!\n");
     printf("pid: %d\tppid:%d\n",getpid(),getppid());                           
     printf("我将睡眠10秒");//睡眠10秒,保证父进程先退出
     sleep(10);
     printf("pid: %d\tppid:%d\n",getpid(),getppid());
     printf("子进程退出!\n");
   }
   else
   {
    
    
     printf("我是父进程!\n");
     sleep(1);
     printf("父进程退出");
   }
   return 0;
 }

在这里插入图片描述
子进程成为孤儿进程,父进程成为1号进程

猜你喜欢

转载自blog.csdn.net/qq_43825377/article/details/113531051