【Linux】进程的概念

文章目录

  • 1. 基本概念
  • 2. 进程的描述
  • 3. 进程的一些基本操作
    • 3.1 查看进程
    • 3.2 结束进程
    • 3.3 通过系统调用获取进程标示符
    • 3.4 通过系统调用来创建子进程
  • 4. 进程状态
    • 4.1 操作系统的进程状态
    • 4.2 Linux对于这些状态的处理方式

1. 基本概念

什么是进程?

在回答这个问题之前想问另一个问题:什么是程序?

  • 我们写的代码(源文件)在经过编译器编译之后生成的是文件,那么就是存放在磁盘中的。所以程序的本质就是文件,在磁盘存放

所谓的进程,就是运行着的程序,我们知道程序的运行肯定是需要CPU做运算的,CPU只能直接与内存做交互,所以程序一定要加载到内存中才能运行(这是体系结构决定的!!)。

同一时间,内存中会有很多进程,所以我们就要这些进程**管理**起来。

那么,怎么管理呢?

2. 进程的描述

在上一篇文章中我们讲到,所谓的管理就是:先描述,再组织

我们一般会采用一个结构体来描述这些进程的相关属性

进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。课本上称之为PCB(process control block), Linux操作系统下的PCB是: task_struct

【Linux】进程的概念_第1张图片

上面是部分内核的代码截图,实际上内核中有关task_struct的代码有很多,主要可以分为以下几类

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

抽象出来大概可以这样表示:(假设系统中进程使用链表的结构组织)

struct task_struct
{
	//进程的所有属性
    //...
  	//进程对应的代码和数据的地址
    //...
  	//下一个进程的地址
    struct task_struct* next;
};

关于task_strcut更详细的讲解,可以看一看这一篇博客:Linux中进程控制块PCB-------task_struct结构体结构(童嫣

有了上述的观念之后,我们从内核的角度来看,进程就是**内核数据结构(task_struct) + 进程对应的磁盘代码**

3. 进程的一些基本操作

3.1 查看进程

  1. 方法一:ps axj可以查看当前所有的进程

ps axj结合管道grep指令可以显示我们想要看到的进程,同时想要看到所有信息的含义,就要加上head -1表示将查询到的第一行数据也显示出来

【Linux】进程的概念_第2张图片

  1. 可以在/proc目录下查看当前所有进程

【Linux】进程的概念_第3张图片

3.2 结束进程

对于一般进程,我们可以使用**[Ctrl + c]结束,也可以使用kill**命令结束

【Linux】进程的概念_第4张图片

3.3 通过系统调用获取进程标示符

每个进程都有一个唯一标识符:PID我们可以通过系统调getpid()用来获取这个唯一标识符

【Linux】进程的概念_第5张图片

注意:

  • 这里的getpid和getppid获取到的就是进程的标识符,其中getpid是获取进程的PID,getppid是用于获取父进程PID

  • 函数的返回值pid_t实际上就是int,只是在系统层面进行了封装

【Linux】进程的概念_第6张图片

image-20231017164705233

可以看到,我们通过 getpid() 和 getppid() 函数得到的值的确是我们进程对应的id;同时,我们发现myproc进程的父进程是 bash,即 shell 外壳,这也侧面证实了我们之前提到的结论 – shell 为了防止自身崩溃,并不会自己去执行指令,而是会派生子进程去执行

同一个程序重新被运行时它的进程id可能与之前不一样,因为它的代码和数据需要重新从磁盘中加载;但是它的父进程id一定是一样的,因为它们都是通过 bash 来执行

【Linux】进程的概念_第7张图片

3.4 通过系统调用来创建子进程

我们可以通过系统调fork来创建子进程

【Linux】进程的概念_第8张图片

【Linux】进程的概念_第9张图片

【Linux】进程的概念_第10张图片

可以看到,所有子进程的id都是0,父进程的id都是子进程的pid,这是因为fork的返回值规定:当fork执行之后将会产生两个进程,其中父进程的返回值是子进程的pid,子进程的返回值是0,fork之后的所有代码都被父子进程共有

4. 进程状态

4.1 操作系统的进程状态

在真正进入的进程状态的学习之前,大家或多或少应该听说过一些进程的状态,比如:挂起,僵尸等等,在进入的进程状态的学习之前,我们需要统一一些观点:

  1. 状态是进程内部的属性,所有的属性都在PCB里

  2. 进程不只会占用CPU资源,也有可能随时要外设资源

  • 运行状态

    进程PCB在运行队列里面的进程状态就是运行状态(不是说进程在运行时才是运行状态)

    运行队列的概念:

    CPU需要对进程做执行,同一时间操作系统内会有很多的进程,那么这些进程谁先谁后呢?此时就需要一个队列将这些进程管理起来,确定谁先执行谁后执行。这个队列里面保存的实际上并不是每个进程对应的二进制代码,而是PCB(task_struct),这个队列就是运行队列(run queue)

    每个CPU拥有一个运行队列

  • 阻塞状态

    我们在上面说到,进程不止会占用CPU资源,也可能随时需要外设资源,当一个进程在运行的过程中需要访问外设资源的时候,由于外设很慢(相对于CPU来说),所以进程需要等待外设,此时CPU就想去处理其他进程,那么当前进程就会进入到阻塞状态

    拓展一下:

    每个CPU执行一个进程,当前进程在处于阻塞状态,等待其他硬件资源的时候,实际上也就是当前进程的PCB进入到了其他硬件的run queue中,也就是说每一个硬件都拥有一个runqueue

  • 挂起状态

    如果系统中存在很多进程,当前进程短时间内不会被调度,代码和数据短时间内不会被执行,此时如果操作系统中的内存不够,就会将这些进程的相关信息保存在磁盘中,节省一部分内存。此时这些被保存在磁盘上的进程就是处于挂起状态

    挂起一定是阻塞的,阻塞不一定挂起

4.2 Linux对于这些状态的处理方式

在上一小节中我们讲到了操作系统内进程的概念性状态,那么在Linux下的表现形式是怎样的呢?

在Linux源码里面能够找到一个数组:task_state_array 罗列了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 *task_state_array[] = {
	"R (running)",		/*  0 */     // 运行状态
	"S (sleeping)",		/*  1 */     // 阻塞状态
	"D (disk sleep)",	/*  2 */     // 磁盘休眠状态/深度睡眠状态(了解)
	"T (stopped)",		/*  4 */     // 暂停状态
	"T (tracing stop)",	/*  8 */     // 该进程正在被追踪(看到的是t状态)
	"Z (zombie)",		/* 16 */     // 僵尸状态
	"X (dead)"		    /* 32 */     // 死亡状态
};

接下来我们来看一些进程状态的例子:

  • 运行状态:

【Linux】进程的概念_第11张图片

image-20231031235745673

  • 休眠状态

【Linux】进程的概念_第12张图片

【Linux】进程的概念_第13张图片

这里出现休眠状态的原因是:调用printf的时候需要访问外设——显示器,由于外设的速度很慢(相对于CPU而言),所以大部分时间都是在等在显示器资源,所以我们能看到的状态大多都是休眠。当然如果非常巧合的话,也是能看到R状态的

  • 暂停状态

【Linux】进程的概念_第14张图片
【Linux】进程的概念_第15张图片

这里扩展一下:S是浅度睡眠,可以被终止;D是深度睡眠,无法被OS杀掉,只能通过断电、自己醒来进行解决。出现的原因一般是由于高IO导致的。

  • t状态

【Linux】进程的概念_第16张图片

【Linux】进程的概念_第17张图片

tracing stop表示该进程正在被追踪


本节完

你可能感兴趣的:(Linux,linux,运维,服务器)