【Linux】进程与进程状态

目录

一、进程

1.1 基本概念

1.2 PCB

1.3 task_struct 内容分类

二、获取进程标识符

三、fork初识

四、进程状态

4.1 操作系统常见的进程状态

4.2 Linux 系统进程的状态

4.3 运行状态

4.4 休眠状态

4.5 停止状态

4.6 终止状态

4.7 僵尸状态

4.8 孤儿进程


一、进程

1.1 基本概念

  • 程序的一个一次执行过程,正在执行的程序等。
  • 内核观点:担当分配系统资源(CPU时间、内存)的实体。

其实,我们在自己启动一个软件,本质其实就是启动了一个进程。在Linux中,运行一条命令,例如:./a.out 时,其实就是在系统层面创建了一个进程。

Linux是可以同时加载多个程序的,Linux是可能同时存在大量的进程在系统中的(OS,内存)。

那Linux系统是如何管理大量的进程的呢?我们往下看。

1.2 PCB

task_struct——PCB中的一种

  • 在 Linux 中描述进程的结构体叫做 task_struct。
  • task_struct 是 Linux 内核中的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。

1.3 task_struct 内容分类

  • 标识符:描述本进程的唯一表示符。用来区分其他进程。
  • 状态:任务状态,退出代码,退出信息等。
  • 优先级:相对于其他进程的优先级。
  • 程序计数器:程序中即将被执行的下一条指令的地址。
  • 内存指针:包含程序代码和进程相关的数据的指针,还有和其他进程共享的内存块的指针。
  • 上下文数据:进程执行时处理器的寄存器中的数据。
  • I/O状态信息:包括显示I/O请求,分配非进程的I/O设备和被进程使用的文件列表。
  • 记账信息:可能包括处理器时间总和,使用的时钟综合,时间限制,记账号等。
  • 其他信息……

所以,如果操作系统想控制一个进程。就可以根据 task_struct 中记录的各种进程信息对其进行管理。

即对进程的管理,变成了对进程 PCB 结构体链表的增删改查。

现在,我们来看看在 Linux 中如何查看当前正在运行的进程。我们先创建一个进程。

然后将其运行起来,接下来我们再复制一个窗口,查看当前进程。

 

 

 查找信息如下:

 我们就成功得到 a.out 的进程号为 10578,为了验证确实是我们刚刚运行的进程,接下来我们使用命令将其终止。

 

我们系统中还存在一个 /proc 目录 将所有的内存级进程以文件系统的形式展现出来,

 比如我们将上面的进程继续跑起来,然后查看其进程ID

 接下来在 proc 中查看当前该进程

 查看其详细属性数据

二、获取进程标识符

接下来,我们学习一个获取 当前进程id 的系统调用。

使用非常简单,如下:

 效果如下:

 其父进程是 bash 

三、fork初识

创建一个子进程。

关于 fork 的三个问题:

  1. 为什么给紫禁城返回0,给父进程返回子进程的 id

为的 是利用父进程区分各个子进程,因为只有一个父进程,而有多个子进程。

     2.父子进程被创建出来,哪个先被执行

不一定!运行顺序是由操作系统决定的

     3.为什么会有两个返回值

因为fork内部 父子进程会执行其各自的 return 语句

 现在我们写一个程序来验证一下fork 函数的功能。

 以下是运行结果:

不能发现,ret 居然有两个值,也就是表示 fork 函数返回了两个值。

所以我们通常使用 if 进行分流

 

 监控起来:

四、进程状态

4.1 操作系统常见的进程状态

  • 新建:创建进程,进程刚被创建。
  • 运行:task_struct 结构体在运行队列中排队,就叫做运行态。
  • 阻塞:等待非CPU资源就绪,阻塞状态。
  • 挂起:当内存不足时,OS通过适当的置换进程的代码和数据到磁盘,进程的状态就成为挂起。

4.2 Linux 系统进程的状态

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

4.3 运行状态

首先我们来写一段程序,来了解当前进程的状态是什么样的。

 运行监控代码:

发现,此时进程处于S状态

因为 printf 是在屏幕上输出,所以当打印时我们会进入阻塞队列,而CPU运行速度很快,导致当前进程大部分时间处于阻塞状态/。  我们大部分时间看到的都是阻塞状态

如果我们将printf语句去掉,再进行监控:

 此时状态就变为了 R 状态

而这个+号呢,表示这个进程为前台进程。 

这个前台进程表示,该进程执行时,输入命令是无效的,但能被Ctrl+c终止掉。其实是占用了bash对话框。

 如果我们想让该进程处于后台运行,则可以加上一个取地址运算符。

 此时进程就会在后台运行,而且ctrl+c无法终止。我们可以使用 kill 命令将其终止。

4.4 休眠状态

休眠状态其实分为中断睡眠和不可中断睡眠,像上面我们实现的S状态,就为可中断睡眠状态,而现在这里主要来阐述一下不可中断睡眠(D),

这里举一个场景。

当一个进程正在往磁盘中写入数据时,而此时内存空间不足,操作系统就有可能强行将该正在写入的进程终止,这种情况是绝对不允许的。

所以,此时出现了不可中断状态,即当一个进程正在进行磁盘写入操作时,操作系统无法将该进程终止。这便是不可中断睡眠状态。

4.5 停止状态

在操作系统中,T(stopped)和t(tracing stop)其实都是用大写T来表示,为了做以区分,所以将两种暂停状态分别以不同的形式展示。

T(stopped)状态主要为我们直接使用命令将一个进程进行暂停。

比如下面一个正在运行的进程。我们使用kill -19 停止该进程。

在kill命令中,有19号信号——暂停信号就可以实现该功能。

 

接下来我们来演示如何使用kill命令实现暂停状态。

现在是一个正在运行的进程。

然后我们使用kill -19进行暂停。

运行的进程报出提示

进程监控中:

 然后我们使用kill -18 继续该进程

 

而 t (sracing stop)通常表示为我们调试过程中的暂停(-g 进入gdg模式)。

然后我们让程序跑起来( r )

 

 暂停和休眠状态的区别: 

休眠是在等待某种资源,暂停相当于阻塞状态。

4.6 终止状态

当一个进程即将结束时,此时进程状态就会被置为 X(终止) 状态,此时 CPU 处理到该进程时就会进行进程释放等一系列操作。

这是一个瞬间的执行的状态。因为CPU的速度非常迅速。

4.7 僵尸状态

  • 僵尸状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程没有读取到子进程退出的返回代码时就会产生僵尸进程。
  • 僵尸进程会以终止状态保持在进程表中,并且会一直在等待进程读取退出状态代码。
  • 所以,只要子进程退出,父进程还在运行,但父进程没有读取到子进程的状态,子进程就会进入 Z 状态。

一个进程已经退出,但是还不允许被OS释放,处于一个被检测的状态

比如一个人突然死亡,但是还不能直接进行处理,处于被法医检测的状态。 

维持该状态,是为了让父进程和OS来进行回收,可用来检测该进程退出的异常性。

演示僵尸状态

4.8 孤儿进程

  • 父进程如果提前退出,那么子进程后退出,进入 Z 之后,那该如何处理?
  • 父进程先退出,子进程就称为“孤儿进程”
  • 孤儿进程被 1 号 inti 进程领养,当然要有 inti 进程的回收 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Brant_zero2022

素材免费分享不求打赏,只求关注

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值