【Linux进行时】进程状态

这篇具有很好参考价值的文章主要介绍了【Linux进行时】进程状态。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

进程状态:

❓假设我们在上课,在B站上上课,请问我们的B站是不是一直运行呢?💡不是的!

❓假设我们同时打开了B站和PDF阅读器时,是怎么运行的呢?

💡每一个进程在CPU跑一会,再从CPU拿下来放上另外一个上去,周而复始,这种叫做分时操作系统

❓那就有一个问题,假设先用B站,为什么先将B站这个进程放上去,而不是PDF阅读器呢?

💡这就取决于进程状态!

思维导图:

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

1.进程的状态

1.1三种基本运行状态

  • 运行状态

🔥R运行状态(running): 并不意味着进程一定在运行中,它表明进程要么是在运行中要么在运行队列里

❓一个进程只要把自己放到CPU上开始运行了,是不是一直要到执行完毕,才把自己放下来?

💡不是,每一个进程都有一个叫做:时间片的概念! 其时间大概是在10 ms左右。所以并不是一个进程一直在执行,而是这多个进程在一个时间段内所有代码都会被执行 —— 这就叫做【并发执行】

所以呢这就一定会存在大量的进程被CPU放上去、拿下来的动作 —— 这就叫做【进程切换】

  • 并发and并行

🔥并行:指的是两个或者多个事件同一时刻发生(可以类比为一个公路,三台车不同道同向行驶)

🔥并发:指的是一段时间内有多个程序同时运行

  • 就绪状态

🔥指的是进程已经处于准备好执行的状态,但是CPU没有空闲的,

  • 阻塞状态和挂起状态

有两个概念:阻塞和挂起!

阻塞:进程因为等待某种条件就绪 ,而导致的一种不推进的状态——进程卡住了——阻塞一定在等待某种资源

就相当于进程太多了,卡着一个进程,在这个进程来看就是在等待CPU调度(某种资源)

🔥阻塞:进程等待某种资源就绪的过程

❓为什么阻塞呢?

💡进程要通过等待的方式,等具体的资源被别人是用使用完之后,再被自己使用。

❓什么是资源呢?💡资源=磁盘或者网卡显卡等各种外设(这是硬件,软件也有)

因为操作系统是通过先描述,后组织的方式来进行管理,假设用struct来代表这些外设用链表连接起来,

❓可以存在大量的进程吗?💡可以的❓要管理吗?💡先描述再组织

假设我们有一个进程task_struct要加载到cpu中,它在等待一个网卡资源

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

CPU说你不能在我上面跑了,所以task_struct就添加到这个队列的尾部等待网卡这个资源

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

也就是我们的task_struct在我们的列入到某种资源的队列当中,它就不会被CPU调度了吗,这不就是卡住了吗,不就是阻塞了吗!!!!

🔥pcb可以被维护在不同的队列中的!

阻塞:阻塞就是不被调度——一定是因为当前进程需要等待某种资源就绪——一定是进程task_struct结构体需要再某种被OS管理的资源下排队

挂起:

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

📚例子

假设task_struct是个下载任务,这里突然没网了,CPU说这个task_struct就不能跑了,task_struct就链接在网卡这个队列的中,这里就是阻塞了

操作系统通过自己的一套算法,把占有内存的,不被调度的进程的数据和代码交换到磁盘当中

磁盘那边放了一份交换后的代码和数据,这里的内存的代码和数据被释放,

在被再次调度前再把代码和数据换回来就可以了

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

🔥其中代码和数据由操作系统暂时将我们的从内存换到磁盘的过程中,此时这个进程就是挂起状态,全称叫做阻塞挂起状态

2.Linux进程状态

task_struct是一个结构体,内部会包含各种属性,包括状态(status)

为了研究 Linux 进程状态,我们把源码先拿出来看看:

/*
* 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):这个状态只是一个返回状态,你不会在任务列表里看到这个状态。

用0表示R,用1表示S,用2表示D,用4表示T,用8表示t,用16表示X,用32表示Z

  • 运行状态

❓进程只要是在R状态,就一定是在CPU上运行吗?💡不一定!

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

所有运行的进程只要在运行的队列中排队就可以了,所以CPU调度进程只要去我们的队列中去挑进程就可以了

❓进程是什么状态?💡一般也看这个进程在哪里排队

进程状态查看我们可以用ps

这里我们也能拿 ps 指令来看进程的状态,我们开小窗输入:

ps axj | head -1 && ps axj | grep process | grep -v grep

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

显然这里S是休眠状态

🔥首先需要声明一点,状态后面跟加号,表示是一个 **前台进程,**你只需要知道的是,能够在键盘上 Ctrl+c 暂停的都可以叫前台进程。

其实我们CPU的运行速度都很快,我们看到这里它一直在打印,其实是显示器(外设)一直在打印,CPU一瞬间就完成了,所以状态是S

我们将test.c中printf注释掉,再试一下

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

我们发现这里变成了R状态了

所以这个进程不访问任何资源,只等你 CPU,只要你被运行期间不访问外设,就不会被阻塞。

不访问外设,那么死也会在等待队列里,一直在等待队列中,这就让 process 达成 R状态!

🔥这里printf的本质就是向外设(网卡、显示器)打印消息,进程只要是R状态,并不直接代表进程正在运行,而代表该进程在运行队列中排队

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

🔥队列由操作系统自己维护

  • 睡眠状态

S状态——休眠状态,可中断休眠,它一直在等待某种资源,其实就是阻塞状态

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

🔥我们一般把 状态叫作 浅度睡眠,也叫做 可中断睡眠

  • 顾名思义,当进程处于 S 状态,它可以随时被唤醒。
  • 不仅仅是操作系统可以唤醒,你也可以唤醒,甚至你想杀掉它都行。
$ kill -9 [pid]

我们用另外一个例子来更直观感受S状态

#include <stdio.h>
 #include <unistd.h>
 int main(void)
 {
   int a=0;
  printf("输入a的值:");
  scanf("%d",&a);
  printf("a=%d\n",a);                                        
  return 0;                                                                          
 }   

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

将该进程运行起来我们可以看到其是出于S+的状态,因为【shell】此时正在等待用户的输入,这个就对应到了我们上面所讲到的 阻塞状态

🔥不仅如此,像我们一直在使用的bash,也可以算是一种【阻塞状态】,一直等待着我们去输入命令行,一旦有了的话它就进行读取

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

  • 深度睡眠模式

这也是一种阻塞模式

"S (sleeping)", /* 1 */
"D (disk sleep)", /* 2 */

这里D模式比S模式多一个disk,磁盘?那肯定跟磁盘有关系

一般而言,在 Linux 中,如果我们等待的是磁盘资源,我们进程阻塞所处的状态就是 D 状态。

与S状态类似,进程处于睡眠状态,但是此刻进程是不可中断的。不可中断,指的并不是CPU不响应外部硬件的中断,而是指进程不响应异步信号。
绝大多数情况下,进程处在睡眠状态时,总是应该能够响应异步信号的。否则你将惊奇的发现,kill -9竟然杀不死一个正在睡眠的进程了!于是我们也很好理解,为什么ps命令看到的进程几乎不会出现D状态,而总是S状态。

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

  • 暂停状态

T状态,暂停状态

我们先通过这个指令来了解一下,我们要使用的就是下面的18和19信号

kill -l

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

进程暂停与进程休眠(阻塞) 没有关系,只是单纯不想让这个进程跑了。

比如有些进程在执行任务时,用户想让这个进程暂停一下,这其实很好理解。

比如看视频,听音乐,下载,都会有暂停。当你点击暂停的时候下载对应的代码就不跑了,此时这个进程你就可以认为是暂停状态。

kill -19 进程pid    暂停该进程
kill -18 进程pid    解除暂停

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

kill -18 pid解除一下

  • 死亡状态

X状态,死亡状态

kill -9 PID

dead 代表死亡,所以 X状态对应的就是 死亡状态

这个没有什么好说的,X 状态的进程就代表死亡了,可以随时等待 OS 来收尸了。

  • 僵尸状态

当一个 Linux 中的进程退出的时候,一般不会直接进入X状态(死亡,资源可以立马被回收),而是进入Z状态

❓当进程退出后不直接变成X状态而是变成Z状态这是为什么呢?

💡当一个进程退出的时候,那最关心它的便是【父进程】。因为这个父进程费了很大的劲才将这个子进程fork出来,此时呢它突然挂掉了,那么此时父进程就必须去关心一下对应的子进程退出时的原因

在这个退出过程中,进程占有的所有资源将被回收,除了task_struct结构(以及少数资源)以外。于是进程就只剩下task_struct这么个空壳,故称为僵尸。
之所以保留task_struct,是因为task_struc t里面保存了进程的退出码、以及一些统计信息。而其父进程很可能会关心这些信息。

我们来造一个僵尸出来看看:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
 
int main(void) {
    pid_t id = fork();
    if (id == 0) {
        // child
        int cnt = 5;
        while (cnt) {
            printf("我是子进程,我还剩下 %ds\n", cnt--);
            sleep(1);
        }
        printf("我是子进程,我已经变僵尸了,等待被检测\n");
        exit(0);
    }
    else {
        // father
        while (1) {
            sleep(1);
        }
    }
}

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

❓如果长时间处于僵尸状态,会有什么结果呢?

💡如果没有人收尸,该状态会一直维护,该进程的相关资源 (task_struct) 不会被释放!内存泄露!一般必须要求父进程进行回收,如何回收的问题我们会在进程控制章节讲解。

❓为什么要main()的返回值呢?💡return 0;这个是进程退出码

🔥如果-个进程退出了,立马X状态,立马退出,你作为父进程,有没有机会拿到退出结果呢? ? ? Linux当进程退出的时候,- -般进程不会立即彻底退出,而是要维持一个状态叫做Z, 也叫做僵尸状态— 方便后续父进程(OS)读取该子进程退出的退出结果!

只要父进程不退出,这个僵尸状态的子进程就一直存在。那么如果父进程退出了呢,谁又来给子进程“收尸”?
当进程退出的时候,会将它的所有子进程都托管给别的进程(使之成为别的进程的子进程)。托管给谁呢?可能是退出进程所在进程组的下一个进程(如果存在的话),或者是1号进程。所以每个进程、每时每刻都有父进程存在。除非它是1号进程。

1号进程,pid为1的进程,又称init进程。
linux系统启动后,第一个被创建的用户态进程就是init进程。它有两项使命:
1、执行系统初始化脚本,创建一系列的进程(它们都是init进程的子孙);
2、在一个死循环中等待其子进程的退出事件,并调用waitid系统调用来完成“收尸”工作;
init进程不会被暂停、也不会被杀死(这是由内核来保证的)。它在等待子进程退出的过程中处于S状态,“收尸”过程中则处于R状态。

  • 孤儿进程

如果父进程 一直存在,子进程退出了,父进程对子进程不管不顾,子进程退出后就要进入僵尸状态

如果有父子两个进程,因为一些问题父进程不存在了,子进程还没有退出呢?

myproc.c

 1 #include<stdio.h>
    2 #include<unistd.h>
    3 int main()
    4 {
    5   pid_t id=fork();
    6   if(id==0)
    7   {
    8     //child
    9     while(1)
   10     {
   11       printf("我是子进程:pid:%d,ppid:%d\n",getpid(),getppid());
   12       sleep(1);
   13     }
   14   }
   15   else
   16   {
   17     //parent
   18     int cnt=10;
   19     while(1)
   20     {
   21        printf("我是父进程:pid:%d,ppid:%d\n",getpid(),getppid());
   22        sleep(1);
   23        if(cnt--<=0)break;                                                                            
   24     }
   25   }
   26   return 0;
   27 }
              

make一下,没有问题

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

这里的$@

和$^

$@代表冒号左侧的,红色的,目标文件

$^代表冒号右侧的,蓝色的,依赖文件

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

while :;do ps ajx | head -1&&ps ajx |grep myproc | grep -v grep;sleep 1;echo "----------";done

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

我们在旁边把程序运行起来

我们发现我们的父进程是5388 ppid 7666

子进程 5389 ppid5388

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

后面父进程中止了,只剩下子进程

子进程是5389 ppid变成了1

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

父进程这时候退出了那是不是应该处于僵尸状态呢?

这里我们为什么没有看到父进程处于僵尸状态呢?

我们在命令行中启动一个进程时,它的父进程是bash

父进程退出之后,它的父进程是bash(命令行解释器),所以这个父进程退出的时候,它的父亲帮他回收了

相当于是我死了,我爹bash帮我回收了

我们发现这个子进程的父进程死掉后,它给自己又找了个爹(1号进程),1好进程可以叫为操作系统

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议

如果不领养会发生什么呢?

如果有一天这个子进程挂了,并且他没有父进程,他就会被操作系统遗忘,就一直处于一种占用操作系统内存空间的情况,也就是内存泄漏

【Linux进行时】进程状态,操作系统,Linux,linux,网络,网络协议文章来源地址https://www.toymoban.com/news/detail-717886.html

到了这里,关于【Linux进行时】进程状态的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Linux进行时】磁盘文件结构

    上篇文章,我们提及文件是存放在磁盘当中,本篇文件我们来了解一下磁盘的结构!!! ❓什么是磁盘? 💡磁盘(disk)是指利用磁记录技术存储数据的存储器。 磁盘是计算机主要的存储介质,可以存储大量的二进制数据,并且断电后也能保持数据不丢失。早期计算机使用

    2024年02月05日
    浏览(37)
  • Linux 使用 PTP 进行时间同步

    PTP(精确时间协议)是一种用于在网络中进行时钟同步的协议。当与硬件支持结合使用时,PTP 能够达到亚微秒的精度,这种精度远高于 NTP 协议。 PTP 时间同步协议的支持分为内核空间和用户空间两部分。在 Linux 系统中,PTP 协议的实际实现称为 LinuxPTP,它是 PTPv2 根据 Linux 的

    2024年04月11日
    浏览(33)
  • Linux--操作系统进程的状态

    【Linux】进程概念 —— 进程状态_linux d状态进程_Hello_World_213的博客-CSDN博客 新建: 字面意思,将你的task_struct创建出来并且还未入队列 运行: task_struct结构体在运行队列中排队,就叫做运行态 阻塞: 等待非CPU资源就绪,阻塞状态   挂起: 当内存不足的时候,OS通过适当的

    2024年02月15日
    浏览(39)
  • MySQL:查询时进行时间比较

    在 MySQL 中查数据的时候,往往需要对记录的创建时间进行筛选,比如只需要查询今年1-5月份的,或者查询距离当前时间多久以前的。 本文介绍了在 MySQL 中查询记录时如何进行时间比较 解决办法:使用 TIMESTAMPDIFF 函数 查询特定时间范围的记录有多种方法,这里介绍几种 查询

    2024年02月16日
    浏览(36)
  • 操作系统练习:在Linux上创建进程,及查看进程状态

    进程在执行过程中可以创建多个新的进程。创建进程称为“父进程”,新的进程称为“子进程”。每个新的进程可以再创建其他进程,从而形成进程树。 每个进程都有一个唯一的进程标识符(process identifier,pid)。在Linux中,init进程是所有其他进程的根进程。 在Linux中,可以

    2024年02月12日
    浏览(44)
  • Arrow:在项目中进行时间处理的强大工具

    目录 一、Arrow简介 二、安装与配置 三、基础功能与使用 1. 日期和时间格式转换 2. 时区处理 3. 时间序列分析 四、进阶应用与案例分析 五、性能与优化 六、最佳实践与经验分享 七、总结与展望 在处理日期和时间时,我们经常需要一个精确、可靠的库来帮助我们。Python的Ar

    2024年02月02日
    浏览(48)
  • Mybatis-Plus如何进行时间日期的比较

    获取数据库中跟当前日期相等的记录时,还是调用eq方法,所以实体类包括数据库中的类型是Date,而不是DateTime,否则只能获取相同时刻的数据。 Mybatis-Plus的时间比较是基于数据库的函数进行的,而不是字符串的比较。在Mybatis-Plus中,可以使用Wrapper对象的 ge、gt、le、lt 方法

    2024年02月11日
    浏览(36)
  • ESP8266调用NTP服务器进行时间校准

    NTP是网络时间协议(Network Time Protocol,简称NTP),是一种用于同步计算机时间的协议。NTP服务器指的是提供NTP服务的计算机或设备。NTP服务器的主要功能是保证网络上的所有设备的时间同步,以确保各个设备相互之间的时间协调一致。NTP服务器通常连接到具有高度精确时间源

    2024年02月08日
    浏览(32)
  • 【数据挖掘】使用 LSTM 进行时间和序列预测

            每天,人类在执行诸如过马路之类的任务时都会做出被动预测,他们估计汽车的速度和与汽车的距离,或者通过猜测球的速度并相应地定位手来接球。这些技能是通过经验和实践获得的。然而,由于涉及众多变量,预测天气或经济等复杂现象可能很困难。在这种情

    2024年02月15日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包