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

linux进程(进程状态)

目录

前言:

正文: 

 1.R运行状态(running)

2.睡眠状态(sleeping)

3.D磁盘休眠状态(Disk sleep) 

4停止状态(stop)

5僵尸状态(Z)

 6 孤儿进程

 补充知识:前后台进程


前言:

为了弄明白正在运行的进程是什么意思,我们需要知道进程的不同状态。一个进程可以有几个状态(在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 */
};

 

  • R运行状态(running: 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里。
  • S睡眠状态(sleeping): 意味着进程在等待事件完成(这里的睡眠有时候也叫做可中断睡眠 (interruptible sleep))。 
  • D磁盘休眠状态(Disk sleep)有时候也叫不可中断睡眠状态(uninterruptible sleep),在这个状态的 进程通常会等待IO的结束。
  • T停止状态(stopped): 可以通过发送 SIGSTOP 信号给进程来停止(T)进程。这个被暂停的进程可 以通过发送 SIGCONT 信号让进程继续运行。
  • X死亡状态(dead):这个状态只是一个返回状态,你不会在任务列表里看到这个状态

正文: 

 1.R运行状态(running)

          运行态具体是指:当操作系统把CPU资源分配给进程时(cup对进程进行调度),进程会在运行队列里面排队(运行状态)在一个时间段内,所有的进程都会被执行,并发执行。在运行状态下,进程会执行它所分配的任务。当进程的时间片用完后,进程就会被挂起(带走自己的上下文),等待下一次CPU调度。

  我们可以看一下在Linux下的R状态【查看进程状态的命令:ps ajx/aux 】。如下:

 process.c

 1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 int main()
  5 {
  6  pid_t id = fork();
  7  if(id < 0){ perror("fork");
  8  return 1;
  9  }
 10  else if(id == 0){
 11     // child
 12      printf("I am child, pid :[%d] ppid:[%d]\n", getpid(),getppid());
 13      sleep(20);
 14 
 15  }else{
 16      //parent
 17      printf("I am parent, pid: [%d] ppid:[%d]\n", getpid(),getppid());
 18     sleep(10);
 19     exit(0);                                                                   
 20 
 21  }
 22  return 0;
 23 }

Makefile 

 myprocess:process.c
  2     gcc -o myprocess process.c                                                 
  3 
  4 .PHONY:clean
  5 clean:
  6     rm -r myprocess
  7 
  8 .PHONY:catP
  9 catP:
 10     ps ajx | head -1 && ps ajx | grep myprocess | grep -v grep
 11         

 通过指令对进程状态进行查看

 

我们会发现不管是父进程还是子进程,我们看到的状态都是S+,这是因为对于cpu来说,将数据回显到显示器的任务在电光火石之间就完成了,我们很难捕捉到,所以我们大部分捕捉的动作他都是在等待队列中进行排队。

        (R+是在运行队列中被操作系统管理这,也是在排队,他不一定被cpu调度)排队类似下图

为了捕捉,我们可以将打印语句屏蔽,让其一直死循环,这样我们就可以在调度的时间片内捕捉到其运行状态。 

 

2.睡眠状态(sleeping)

 

  睡眠状态是指:当进程被调用而等待某个事件的发生时,该进程就会进入睡眠状态。通俗来讲,当我们要完成某种任务的时候,任务条件不具备,需要进程进行某种等待。(也叫进程阻塞

  进程等待时,都是在等待CPU资源吗?答案是:并不是!

  睡眠状态被认为是一种阻塞状态,因为该进程在等待发生的事件情况下不能真正地执行,所以CPU的资源也就会被阻塞。只有当该事件发生,进程才能被唤醒并继续执行。

 补充:s+是一种前台进程,我们可以通过输入信号将其关闭,也就是键盘上的ctrl+c将进程杀死,(会在信号章节进行详细介绍)。

 

3.D磁盘休眠状态(Disk sleep) 

D磁盘休眠状态(Disk sleep)表示进程因等待磁盘I/O操作时而被阻塞,并且进程等待的操作可能会很慢,也可能永远不会完成。当出现大量相同操作的时候,就会出现休眠状态。

  例如有一个进程需要把数据写入磁盘,且数据量很大。而写入磁盘的过程相对来说并不是很快,进程需要等待一段时间。等待的过程中,同时也占用了CPU的资源, 我们都知道操作系统是不会浪费任何内存,所以他有杀死进程的功能。如果该进程写入的数据很重要,需要磁盘读取数据完成后的返回信息。但也可能会被误操作给删除。所以给他一个免死金牌D状态,该进程不可被操作系统终止。

  在Linux系统中,有些进程可能预期会处于D状态,例如,磁盘I/O操作比较耗时的进程。而对于其他类型的进程,处于D状态通常是不正常的,需要进行诊断和解决。常用的解决方法包括重启系统、更换设备等。
 

4停止状态(stop)

         

  T停止状态(stopped)表示进程已经被挂起,不再运行,但是它尚未完成或终止。进程可以进入停止状态是由于收到一个SIGSTOP、SIGTSTP、SIGTTIN或者SIGTTOU信号,以及调试器进程发送的SIGHUP、SIGINT、SIGQUIT、SIGILL、SIGTRAP、SIGABRT、SIGBUS、SIGFPE、SIGSEGV、SIGPIPE、SIGALRM、SIGTERM、SIGURG、SIGXCPU、SIGXFSZ和SIGSTOP信号。

我们可以利用kill - 18 kill-19让进程 恢复或者暂停。

5僵尸状态(Z)

与死亡状态相对应的还有一个 僵尸 T 状态

通俗来说,僵尸状态 是给 父进程 准备的
当 子进程 被终止后,会先维持一个 僵尸 状态,方便 父进程 来读取到 子进程 的退出结果,然后再将 子进程 回收。
单纯的在 bash 环境下终止 子进程,是观察不到 僵尸状态 的,因为 bash 会执行回收机制,将 僵尸 回收。

  • 我们可以利用 fork() 函数自己创建 父子进程 关系,观察到这一现象

 

1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 int main()
  5 {
  6  pid_t id = fork();
  7  if(id < 0){ perror("fork");
  8  return 1;
  9  }
 10  else if(id == 0){
 11 
 12      // child                                                                  
 13      printf("I am child, pid :[%d] ppid:[%d]\n", getpid(),getppid());
 14      sleep(5);
 15 
 16  }else{
 17      //parent
 18     printf("I am parent, pid: [%d] ppid:[%d]\n", getpid(),getppid());
 19     sleep(20);
 20     exit(0);
 21 
 22  }
 23  return 0;
 24 }
~
~
~

 

 

 6 孤儿进程

  • 通过程序创建 父子进程
  • 通过指令终止 父进程,此时 子进程 会被OS领养
  • 子进程 的 父进程 变为 1号进程
  • 子进程 就变成了一个 孤儿进程

我们可以通过以下代码验证当父进程先退出的时候,子进程是不是被1号进程接管。

 1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  4 int main()
  5 {
  6  pid_t id = fork();
  7  if(id < 0){ perror("fork");
  8  return 1;
  9  }
 10  else if(id == 0){
 11 
 12      // child
 13      printf("I am child, pid :[%d] ppid:[%d]\n", getpid(),getppid());
 14      sleep(35);
 15 
 16  }else{
 17      //parent
 18     printf("I am parent, pid: [%d] ppid:[%d]\n", getpid(),getppid());
 19     sleep(5);                                                                  
 20     exit(0);
 21 
 22  }
 23  return 0;
 24 }
~

 

 补充知识:前后台进程

Linux中运行的程序可以在前台(foreground)或者后台(background)运行。前台程序是在当前终端会话中运行的程序,而后台程序则是在系统内部运行的,没有与用户终端会话相关联。上述带 ‘+’ 号的就是在前台运行的程序,不带 ‘+’ 号的就是在后台运行的程序。

  当用户在终端中输入运行一个程序的命令时,该程序默认以前台方式运行,它会在终端上打印输出并且用户必须等待程序执行完成。

  如果在命令末尾加上 & 符号,就可以让程序在后台运行。具体如下图:

 

  如果需要与后台程序交互,可以使用一些特殊的命令,如:jobs, fg等,来查看和控制程序的状态。 fg 指令就可吧后台进程转换到前台运行。例如: 


$ jobs       #查看后台运行的程序
$ fg %1     #将后台中的程序1转为前台运行


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

相关文章:

  • 后端接口返回二进制文件,前端 window.opent预览展示
  • Vue常用加密方式
  • 对称加密与非对称加密:密码学的基石及 RSA 算法详解
  • 计算机网络分析题
  • Leetcode 找出字符串中第一个匹配项的下标
  • 【随机种子】Random Seed是什么?
  • 再说开源软件
  • 瑞吉外卖实操笔记五----店铺营业状态设置与用户端微信登录实现
  • Junit常用注解
  • 如何在苹果Mac上进行分屏,多任务处理?
  • 深入学习《大学计算机》系列之第1章 1.7节——图灵机的一个例子
  • 蓝桥杯每日一题之内存问题
  • Elementplus报错 [ElOnlyChild] no valid child node found
  • Spring Boot与Kafka集成教程
  • Django模板(二)
  • 每天上班都疲惫不堪,怎么办?
  • 【C/C++ 17】继承
  • 鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之ScrollBar组件
  • 安全SCDN有什么作用
  • PMP考试之20240211
  • JAVA中的单例模式->懒汉式
  • 在 Docker 中启动 ROS2 里的 rivz2 和 rqt 出现错误的解决方法
  • 《Django+React前后端分离项目开发实战:爱计划》 01 项目整体概述
  • DP读书:《openEuler操作系统》(九)从IPC到网卡到卡驱动程序
  • 【FPGA开发】Modelsim和Vivado的使用
  • mysql底层结构