【Linux】进程的概念|查看进程的方法|子进程

➡️基本概念

在了解进程之前需要知道什么是程序?
对于计算机而言,程序就是系统可以识别的一组有序的指令。程序能指挥计算机执行我们想要它做的动作。程序储存在磁盘上,在执行时从磁盘到内存再到寄存器,最后被CPU执行。
进程的课本概念:程序的一个执行实例,正在执行的程序等,但这只是课本的概念。

“先描述”进程(PCB)

不可能在内存上只有一个进程,一般有很多程序在运行,那么操作系统怎么对这些进程进行管理呢?

一谈到操作系统的管理那么就一定是先描述。再组织,就像这样的先描述再组织的方式是操作系统一贯的作风。不了解先描述再组织的老铁可以看这篇文章文章链接

把程序加载到内存可不仅仅是把代码拷贝到内存,操作系统为了维护和管理这个进程也要创建对应的管理数据结构,就是这里的PCB(process control block),在Linux操作系统中描述进程的结构体叫做task_struct。
进程信息被放在一个叫做进程控制块的数据结构中,可以理解为进程属性的集合。
本质上是一个装有进程属性的结构体。task_struct是Linux内核的一种数据结构,它会被装载到RAM(内存)里并且包含着进程的信息。一个程序对应一个task_struct结构体对象。

task_ struct内容分类

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

“再组织”进程

可以在内核源代码里找到它。所有运行在系统里的进程都以task_struct链表的形式存在内核里,
将程序对应一个task_struct结构体对象与它自己的代码和数据关联起来,根据程序对应PCB(task_struct)优先级和各种属性的不同,CPU对他们进行着不同的操作。

在这里插入图片描述

最终结论:

现在返回来看什么是进程,现在对于进程的概念就应该是:内核数据结构(task_struct)+进程对应的磁盘代码

进程的一些特性:

1️⃣竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级。
2️⃣独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰。
3️⃣并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行。
4️⃣并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

➡️如何查看进程

在window下我们可以直接通过任务管理器查看进程。
在这里插入图片描述
在Linux下如何查看进程呢?

方法一:

我这里先创建一个死循环程序
在这里插入图片描述
然后运行程序,在命令行输入

ps ajx |head -1 && ps ajx |grep 'myproc'
或者
ps ajx |head -1 && ps ajx |grep "myproc"
或者用shell脚本设置一个循环来死循环打印进程信息
while :; do ps axj |  head -1&& ps axj |grep myprocess | grep  -v grep; sleep 1; done

在这里插入图片描述

在这里插入图片描述
PPID是父进程IDPID是这个进程自己的ID,PGID是这个进程的组ID,STAT代表这个进程的状态
UID是用户ID,COMMAND就代表我是哪一个进程

想杀掉这个进程用kill -9 这个进程的PID
在这里插入图片描述

方法二:

进程的信息可以通过 /proc 系统文件夹查看。
在这里插入图片描述
其实一个一个的进程也就相当于/proc下的一个个目录

➡️通过系统调用获取进程标识符

  • 如:要获取PID为1的进程信息,你需要利用cd /proc/1查看/proc/1这个文件夹。 那么怎么在程序里就直接获取PID呢?

其实Linux提供了一个系统调用接口,叫做getpid()
运行man getpid认识一下getpid()

在这里插入图片描述
在我们的程序里添加这个系统调用,就会自动把当前程序的PID显示出来。
在这里插入图片描述
在这里插入图片描述
当我们利用kill -9 命令将这个11167的进程杀掉之后,那么在/proc下就看不到11167这个目录了。

然后我们再使用一下getppid来获取一下当前进程的父进程,

在这里插入图片描述
通过编译之后,多次运行,我们可以发现,PID也就是下面的id号是运行一次就变一次,而父进程pid号7139是一直都不变的,那么为什么呢?
在这里插入图片描述
我们在命令行输入ps ajx | head -1 && ps ajx | grep 7139
在这里插入图片描述
就可以看到7139是一个bash,我们把这个bash用kill命令杀掉的话,那我们的各种ls、cd等等一些个命令都运行不了了,我们退出shell下次再进行这样的操作,发现他们的父进程还是bash,所以其实在Linux命令行上启动的进程, 一般它的父进程没有特殊情况的话,都是bash!

➡️通过系统调用创建进程子进程(fork)

  • 运行 man fork 认识fork
    在这里插入图片描述
  • 下面是fork的返回值,惊奇的发现fork竟然有两个返回值
RETURN VALUE
       On success, the PID of the child process is returned in the parent, 
       and 0 is returned in the child.  
       On failure, -1 is returned in the parent, no child process is created, and
       errno is set appropriately.
  • 父子进程代码共享,数据各自开辟空间,私有一份。fork执行之前只有一个父进程,函数执行之后是父进程+子进程

实验一:

下面用vim工具写一段代码:

在这里插入图片描述
运行起来可以看到printf被执行了两次,其中上面是父进程打印的,下面的是子进程打印的

在这里插入图片描述
通过ps ajx| head -1 && ps ajx | grep 29346查看这个29346是谁,从下面结果就可以清晰的看到它是bash
在这里插入图片描述
从上面的结果来用一句形象的话来描述上面的现象就是:29945是爸爸,29346(bash)是爷爷,29946是孩子。

实验二:

代码:
在这里插入图片描述
执行结果:
在这里插入图片描述

RETURN VALUE
       On success, the PID of the child process is returned in the parent, 
       and 0 is returned in the child.  
       On failure, -1 is returned in the parent, no child process is created, and
       errno is set appropriately.

通过前面的介绍已经知道fork是有两个返回值的,可以看到其实它一个返回值返回给了父进程,这个返回值从上面可以看出它是子进程的id,另一个返回值是0,被返回给了子进程。

  • fork 之后通常要用 if 进行分流

实验三:

代码:
在这里插入图片描述
执行结果:
在这里插入图片描述
可以看到在fork之后,会有父进程+子进程连个进程在执行后续代码。fork之后的代码,被父子进程共享,通过返回值的不同,让父子进程执行后续共享的代码的一部分。这就叫所谓的并发式编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

有效的放假者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值