【Linux修炼】8.进程概念(二)

简介: 【Linux修炼】8.进程概念(二)

4.两种特殊的进程



4.1僵尸进程


上述已经提到过僵尸状态的进程的概念,那么在这里就详细演示一下僵尸进程的具体面貌:(代码)

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main()
{
    int id = fork();
    if(id > 0)
    {
        while(1)
        {
            printf("我是父进程,pid: %d, ppid: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else if(id == 0)
    {
        while(1)
        {
            printf("我是子进程,pid: %d, ppid: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else 
    {
        perror("fork fail");
        exit(-1);
    }
    return 0;
}


我们发现,通过sleep,为4044的子进程被杀掉了,此时父进程并没有处理子进程,因此出现了default(失效)并且子进程变成了Z状态,并且左侧也验证了只剩下父进程,并没有子进程的存在了!如果父进程一直不对这个子进程进行收取,那么这个子进程就会变成僵尸进程。


微信图片_20230225131125.png


4.2孤儿进程


1. 什么是孤儿进程?


上述我们提到,如果一个子进程被杀,那么其暂时就会处于僵尸状态,如果没有父进程回收就会变成僵尸进程。那如果是父进程被杀,父进程和子进程又会发生什么呢?事实上,父进程被杀,即父进程比子进程先退出,那么剩下的子进程就叫做孤儿进程。 这种现象也确实存在。


2.孤儿进程的表现形式


我们知道,如果一个进程变成了僵尸进程,其进程状态就会变成T,那我们来看看孤儿进程是如何表现的。


  1. 首先,我们仍然展示一下具体代码:(和僵尸进程中的代码一致)


#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main()
{
    int id = fork();
    if(id > 0)
    {
        while(1)
        {
            printf("我是父进程,pid: %d, ppid: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else if(id == 0)
    {
        while(1)
        {
            printf("我是子进程,pid: %d, ppid: %d\n", getpid(), getppid());
            sleep(1);
        }
    }
    else 
    {
        perror("fork fail");
        exit(-1);
    }
    return 0;
}


接下来,复制SSH渠道,杀掉父进程,观察子进程的状态。(父进程也关注一下)动图展示:


微信图片_20230225131240.gif

结果:

微信图片_20230225131245.png

我们发现,有三处发生了变化,其一是父进程被杀之后,变成了S状态,但是这样不就与我们之前的僵尸状态违背了吗?为什么不是T状态呢?事实上我们在上述僵尸状态中讲过,在被父进程回收之前就是T状态,而这个父进程被杀掉,也有其相应的父进程,这个父进程的父进程就是bash,bash相比较普通的父进程,bash进程将他的子进程进行了及时的回收,而这个父进程却不会对其子进程进行及时的回收。因此对比之下bash进程比一般的父进程更加负责。


其二就是我们子进程的状态,由S+变成了S进程,即从前台进程变成了后台进程,这就是孤儿进程最明显的变化,变成后台进程后不能通过ctrl c快捷键暂停,而只能通过kill结束进程(当然,断电处理也可以,但是没必要)


其三我们发现,子进程的PPID也就是这个子进程的父进程因为被杀掉而变成了1,而这个1所对应的其实就是操作系统,即父进程被杀掉之后,这个子进程被操作系统所领养,操作系统就变成了他的父进程,这也正对应了冯诺依曼体系中的进程被操作系统所管理。如果不领养,那么当这个子进程被杀掉时,就会因为没有后续处理从而将变成僵尸进程,这是整个体系都不愿看到的结果,因此操作系统必须领养。



5.进程优先级(了解范畴)



对于进程优先级,我们采取三个问题将这个概念解释清楚:


1. 什么叫做优先级?


只凭字面意思来说,优先级和权限有没有区别呢?答案是一定有的,即权限是能做或者不能做的问题,而优先级是先做和后做的问题。


2. 为什么会存在优先级?


那为什么会存在优先级呢?那是因为在一定范围内的资源是有限的,为了获得这个资源就必须赶在其他人的前面,否则就有可能最后什么也捞不到。举个例子:我们知道在一个内存中有许多的进程,但是CPU只有一个,这个时候进程为了能够先执行就会产生优先级的概念,即重要的进程先运行,其他的进程后运行。


3. Linux优先级的特点


在Linux操作系统中,在ps ajx 选项中出现的PRI(priority)下的数字就是所谓的优先级,即这个数字和我们现实中的排名一样,数值越低,优先级就越高。而这个数值PRI = 基础数值(80) + nice值,(NI)nice值是可以进行修改的,其修改区间为[-20,19],因此PRI的范围为[60, 99]。


仍然是利用孤儿进程的代码:

演示:通过指令ps -l PID


微信图片_20230225131356.png

我们发现,初始状态下,PRI和NI的值为80和0,加起来就是基础数值。

接下来进行修改:

通过如下指令:进入top后按“r”–>输入进程PID–>输入nice值

第一步:sudo top(改变优先级需要提权)

微信图片_20230225131400.png


第二步:输入r,输入对应要修改优先级进程的PID,回车


微信图片_20230225131443.png

第三步:输入修改之后的NI值。回车。

微信图片_20230225131446.png

这样就修改完成了,接下来我们看一看结果:

微信图片_20230225131449.png

这样其PRI就变成了80+19 = 99。


6.进程的其他概念



竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级

独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰

并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行

并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发(一段时间采用:时间片轮转的方式)


7.进程切换



在定义之前,我们需要举例引入进程切换的概念,对于我们常用的手机、电脑等,一般只有一个CPU,我们知道一个CPU一次只能运行一个进程,但是我们发现,在电脑上,我们可以在打开PDF的同时,去浏览一些其他网页,即同一个时间段内,多个进程可以被CPU同时运行,这是为什么呢?事实上这就是进程切换的效果。


进程切换的理解: 由于Linux的CPU一次只能运行一个进程,但是我们一个时间段内却可以运行多个进程,因为CPU是足够快的,因此我们人感觉的一瞬间就相当于CPU的一个时间段,想一想1ms对于人来说算是一瞬间,但是CPU却是以纳秒为单位计时的,因此在我们自身感觉到的一瞬间也就是CPU的一个时间段内,会将执行的多个进程按照一定的周期分别运行,一个运行到固定周期之后就强行拉入运行队列的末尾等待,就这样直到完成所有执行的进程,这就是进程之间在一定的时间内相互切换,叫做进程切换。而所谓的周期就是时间片。(并发中提到)


进程的上下文保护:


当CPU在进行进程切换的时候,要进行进程的上下文保护,当进程在恢复运行的时候,要进行上下文进程的恢复!


上下文是什么呢?


进程在运行时会产生非常多的临时数据,同时CPU中存在一套寄存器硬件,当进程运行时,进程的PCB会被放入CPU内的寄存器中,此时CPU就可以通过进程PCB(暂时理解成PCB)得到进程代码数据的地址;CPU在运行进程时所产生的大量的临时数据也都会被保存在寄存器中;因此在进行进程切换时需要进行进程的上下文保护与上下文恢复,进程停止运行时将寄存器里面的数据保存起来,进程重新运行时将保存的数据再放入到寄存器中;所以进程的上下文就是一个进程完成他的时间片后在CPU中所保存的临时数据。



相关文章
|
4天前
|
资源调度 Linux 调度
Linux c/c++之进程基础
这篇文章主要介绍了Linux下C/C++进程的基本概念、组成、模式、运行和状态,以及如何使用系统调用创建和管理进程。
14 0
|
2月前
|
网络协议 Linux
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
Linux查看端口监听情况,以及Linux查看某个端口对应的进程号和程序
333 2
|
2月前
|
Linux Python
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
linux上根据运行程序的进程号,查看程序所在的绝对路径。linux查看进程启动的时间
56 2
|
4天前
|
消息中间件 Linux API
Linux c/c++之IPC进程间通信
这篇文章详细介绍了Linux下C/C++进程间通信(IPC)的三种主要技术:共享内存、消息队列和信号量,包括它们的编程模型、API函数原型、优势与缺点,并通过示例代码展示了它们的创建、使用和管理方法。
12 0
Linux c/c++之IPC进程间通信
|
4天前
|
Linux C++
Linux c/c++进程间通信(1)
这篇文章介绍了Linux下C/C++进程间通信的几种方式,包括普通文件、文件映射虚拟内存、管道通信(FIFO),并提供了示例代码和标准输入输出设备的应用。
10 0
Linux c/c++进程间通信(1)
|
4天前
|
Linux C++
Linux c/c++之进程的创建
这篇文章介绍了在Linux环境下使用C/C++创建进程的三种方式:system函数、fork函数以及exec族函数,并展示了它们的代码示例和运行结果。
10 0
Linux c/c++之进程的创建
|
8天前
|
Ubuntu Java Linux
Linux操作系统——概念扫盲I
Linux操作系统——概念扫盲I
22 4
|
21天前
|
Linux Shell
6-9|linux查询现在运行的进程
6-9|linux查询现在运行的进程
|
4天前
|
Linux C++
Linux c/c++进程之僵尸进程和守护进程
这篇文章介绍了Linux系统中僵尸进程和守护进程的概念、产生原因、解决方法以及如何创建守护进程。
11 0
|
18天前
|
数据采集 消息中间件 并行计算
进程、线程与协程:并发执行的三种重要概念与应用
进程、线程与协程:并发执行的三种重要概念与应用
38 0