linux入门---理解进程概念

什么是进程

大家在课本上经常可以看到进程得概念为:一个运行起来的程序就将其称之为进程或者加载到内存中的程序就称之为进程再或者进程相比于程序具有动态属性等等,这些都可以称之为进程的概念,但是这些概念都十分的难懂,所以接下来我将带着大家一步一步的从最基础的概念了解进程。首先看看下面的图,正方形的是内存圆柱则是磁盘:
在这里插入图片描述
我们平时写的各种程序本质上就是文件,比如说之前写的进度条,shell排序,三子棋等等这些都是文件,而这些文件都被放在磁盘上面
在这里插入图片描述
当我们将这些程序运行起来时,这些文件就会被加载到内存里面,然后cpu就可以从内存中读取该文件并执行里面的内容,比如说我们想要运行进度条这个文件,那么内存就会把进度条对应的文件加载进内存,然后cpu再从内存中读取进度条文件的内容执行对应的代码:
在这里插入图片描述
可是这里就会存在一个问题,从磁盘中加载到内存的文件不止这一个文件,而是有很多很多个文件在内存当中
在这里插入图片描述
当内存中加载了很多程序的时候这些程序都是需要被管理的,比如说哪些程序先被执行哪些后被执行,哪些程序执行完了需要做一些处理,哪些程序要增加被调度的次数,这个程序执行到哪了,那个程序执行到哪了等等都是要被操作系统管理的,而我们之前说过管理的本质就是就是对数据进行管理,管理的方法就是先描述再组织,操作系统为了描述各种被加载进来的程序的数据就会创建一个PCB的概念,PCB的全称是process control block翻译成中文就是进程控制块,这个东西在linux内核中就是一个名为task_struct的结构体,这个结构体里面就会装着与程序(或者进程)相关的所有属性比如说进程的状态,进程的优先级,进程的id等等而且结构体里面还会包含进程对应的代码的地址和下一个PCB所在的地址,

struct task_struct
{
	//该进程的所有属性
	//该继承对应的代码和数据的地址
	struct task_struct *next//指向下一个PCB
}

这里大家要注意的一点就是:加载进来的程序里面不存在该程序的各种属性,他里面只有我们写的各种代码数据和逻辑,而这里出现的各种进程的属性和task_struct结构体都是程序加载到内存时操作系统创建出来的与该程序无关,那么这里我们就可以将上面的图进行一下修改,磁盘中有很多的程序要被加载到内存里面然后每加载进来一个程序操作系统都会创建task_struct结构体(PCB对象)来描述这些程序,并通过结构体里面的指针将这些PCB链接起来
在这里插入图片描述
当cpu想要调度一个优先级最高的进程时,操作系统就会遍历这里的PCB找到优先级最高的PCB,再通过PCB里面的地址找到该程序在内存中的位置并将该程序加载到cpu里面执行,当有一个进程想要退出回到磁盘时,操作系统就会遍历这里的PCB找到是否有一个程序的状态为死亡,当操作系统找到了一个PCB里面的程序状态为死亡时,他就会将该PCB指向的代码和数据进行释放然后再把这个PCB进行释放,也就是说通过这样的结构我们把对进程的管理转换成为了对进程对应的PCB进行相关的管理,把对PCB的管理转换成为了对链表的增删查改。当我们想要执行一个程序时也就是将该程序加载进内存然后操作系统会创建一个PCB来描述这个程序,并把创建出来的PCB链接进内存中已有的PCB链表里面,当我们想要删除一个进程时也就是将PCB组成的链表里面的一个元素和该元素组成的代码数据进行删除,当我们想要查找一个进程时也就是遍历查找进程所组成的PCB链表再通过PCB找到对应的代码。linux内核中有一个名为task_struct的内核结构体,内存中每加载进来一个程序就会根据该结构体创建出来一个task_struct结构体对象并将该对象和你的代码数据关联起来,最后完成了先描述再组织的工作所以进程的真正概念=内核数据结构(task_struct)+进程对应的磁盘代码。

查看进程

首先创建一个文件在文件里面写入一个死循环代码:

  1 #include<stdio.h>  
  2 #include<unistd.h>  
  3 int main()  
  4 {  
  5     while(1)  
  6     {  
  7         printf("我是一个进程!\n");  
  8         sleep(1);  
  9     }  
 10     return 0;                                                                                                                                
 11 }                      

然后创建一个makefile文件并且完成基础的功能
在这里插入图片描述
这时我们就可以输入make指令生成可执行程序
在这里插入图片描述
这里大家要注意的一点就是此时的myproc不是进程,他只是一个普通的文件而已,只有当我们将这个可执行程序运行起来时这个myproc才是进程,那么这里就可以将这个程序运行起来:
在这里插入图片描述
那么这时的myproc就是一个进程,我们再复制一个ssh渠道在里面输入ps ajx指令,这个指令的功能就是显示当前机器上的所有进程
在这里插入图片描述
按下回车之后我们就看到这里显示了很多内容,由于内容十分的多这里就可以采用管道加grep指令的方式找到我们想要的进程ps ajx|grep 'myproc'
在这里插入图片描述
但是使用这种方式查找进程的时候会有一个缺点,grep也是一个指令当我们使用这个指令查找内容的时候这个指令也就变成了一个进程,所以当我们使用grep指令来筛选一个程序的时候也会把grep指令自己也筛选出来,所以这里就显示了两个结果。当程序运行起来时这里会显示两个结果我们使用ctrl c终止程序之后再来使用相同指令查找时就可以发现这里只会显示一个结果就是grep指令地那个结果:
在这里插入图片描述
使用这个指令显示进程的时候会出现一堆数据,这些数据代表什么意思我们无法知道,所以就得使用这个指令来显示进程的标题:ps ajx | head -1
在这里插入图片描述
将上面的两个指令相结合就可以在查找指令的时候显示出对应的标题:ps ajx | head -1 && ps ajx|grep 'myproc'
在这里插入图片描述
PPID指的是这个进程的父进程ID,PID指的是当前进程的ID,PGID指的是当前进程的祖ID,SID指的是会话ID,TTY代表的是终端,STAT代表的是当前进程的状态,UID代表的是用户ID,COMMAND就代表的是我是哪一个进程,每一个进程都有一个属于自己的PID,这个PID就相当于每个人的身份证一样独一无二并且代表着某一个人,我们可以使用进程的PID来做一些事情,比如说结束一个进程就可以使用kill -9 PID指令,那么这里我们就可以根据myproc进程的PID来结束该进程该操作如下:
在这里插入图片描述
我们可以看到这个指令执行成功之后左边的屏幕上就显示出来了killed字样表示当前的进程已经被杀死了结束了再使用ps ajx | head -1 && ps ajx|grep 'myproc'指令查看正在运行的进程时就只显示了一个内容:
在这里插入图片描述
在程序里面我们可以使用getpid函数来获取当前进程的PID
在这里插入图片描述
这个函数没有参数并且这个函数的返回值就是当前进程的pid,所以我们可以把之前写的文件进行修改,在其打印内容的时候顺便打印出当前进程的pid,那么这里修改后的代码如下:

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<unistd.h>
  4 int main()
  5 {
  6     while(1)
  7     {
  8         printf("我是一个进程!我的PID为:%d\n",getpid());
  9         sleep(1);
 10     }                                                                                                             
 11     return 0;                                 
 12 } 

make一下并执行一下更新了的可执行程序就可以看到这样的现象:
在这里插入图片描述
我们上面说过当一个进程加载进内存的时候操作系统会做一些操作来方便进程的管理,那我们能不能看到操作系统所做的一些操作呢?答案是可以的。在根目录下有一个名为proc的目录
在这里插入图片描述
这个目录里面装的都是与进程有关的目录,我们每加载一个进程到内存里面,都会在这个目录里面创建一个子目录且目录名为该进程的PID,比如说执行一下上面的程序就可以看到当前有个进程的PID为:32027
在这里插入图片描述
然后就可以使用下面的指令查找一下就可以看到这里确实有一个名为32027的目录:
在这里插入图片描述
然后我们再使用kill -9 32027指令杀死该进程之后再使用上面的查找指令时就会发现这里没有找到任何内容:

在这里插入图片描述
那么这就说明我们没执行一个可执行程序就都会在/proc/路径下创建一个名为该进程pid的目录,一旦这个进程结束了被杀死了这个目录也就会删除,我们再运行一下上面的程序:
在这里插入图片描述
然后进入1451目录就可以看到这个目录下有非常多关于该进程的属性:
在这里插入图片描述
这里大家可以看到有一个链接文件名为exe,这个文件的作用就是记录该进程的代码数据在磁盘上面的位置,此时这个程序正在运行,那如果我们将这个程序所在的磁盘上的文件删除时会出现什么样的情况,我们来看看下面的操作:
在这里插入图片描述
我们可以看到当删除磁盘上的文件时这个进程依然在执行,但是1451目录里面exe链接文件变成了红色并告诉我们磁盘上的文件已经不存在了,那么这就说明当一个文件被加载进内存时,磁盘上的文件操作并不会影响内存中已经被执行的文件。 那么以上就是本篇文章的全部内容希望大家能够理解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叶超凡

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值