目录
一、进程基本概念:
进程的概念:
基本概念:是计算机中的程序关于某数据集合上的一次运行活动, 是系统进行资源分配的基本单位 ,是操作系统结构的基础。
我们在windows系统下打开任务管理器时也可以看到相应的进程:
我们可以通过上图发现,进程会占用CPU和内存,当一个可执行文件加载到内存的时候,就是一个进程。对于操作系统来讲,二进制指令繁杂又冗余,又难以管理。但是操作系统又必须对每个进程所做的事情进行清楚的描述,为此,操作系统会生成一个内核结构体来代表处理不同的实体,而这个就是PCB结构体,它包含了这个进程的所有信息。一个进程对应着一个PCB结构体,当有多个可执行程序被加载到内存时,就会生成多个PCB结构体,而在任何时候操作系统都能够跟踪进程对应的PCB结构体从而获取进程的信息。
二、进程的五种基本状态:
**创建状态:**进程在创建时需要申请一个空白PCB,向其中填写控制和管理进程的信息,完成资源分配。如果创建工作无法完成,如资源无法满足,就无法被调度运行。
**就绪状态:**进程已经准备好,已分配到所需资源,只要分配到CPU就能够立即运行。
**运行状态:**进程处于就绪状态被调度后,进程进入运行状态。
**阻塞状态:**正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用。
**终止状态:**进程结束,或出现错误,或被系统终止,当进入终止状态时。无法再返回运行状态。
三、Linux的进程状态:
在Linux的源码中关于进程状态的描述是一个指针数组,其中各个字母的含义为:
- R (running):该进程正处于运行状态中。
- S (sleep):该进程目前正在睡眠状态,但可以被唤醒。
- D (disk sleep):该进程处于不可被唤醒的睡眠状态,通常这个进程可能在等待I/O的情况。
- T (stopped):停止状态,该进程收到一个暂停信号,暂时暂停该进程。
- t (tracing stop**):追踪停止状态,通常在断点调试时,进程处于此状态。**
- X (dead):进程处于终止状态,这个状态是用来告诉操作系统的,我们观察不到此状态。
- Z (Zombie):僵尸状态,进程已经终止,但是却无法被删除至内存外。
在Linux下我们可以通过ps ajx命令来查看系统所有的进程:
PID是一个用于在操作系统中唯一标识和区分每个运行中的进程的标识符,每一个进程都有一个独特的PID,由操作系统动态分配,PID就存放于进程对应的PCB中。
我们可以写一个简单的死循环程序(生成的可执行文件名为 test )让其运行并查询到这个进程:
cpp
#include <iostream>
2 using namespace std;
3 int main()
4 {
5 while(1);
6 return 0;
7 }
在Linux系统下可以通过以下命令来查询指定进程:
ps ajx | grep test
grep后跟生成的可执行文件的名称,或者对应的进程ID
或者也可以加上一些 (如下) 将对应的头标在第一行显示出来(修饰一下,比较好看)
ps ajx | head -1 && ps ajx | grep test
关于bash进程:
当我们查询test的父进程时,可以看到这是一个bash进程,而bash就是Linux中的shell解释器,每一个已登录的用户在终端登录后,Linux系统会给这个用户一个bash进程,bash进程通常运行于文本窗口中,并能执行用户直接输入的命令,且bash进程是大部分命令行启动的程序的父进程。
例如:在命令行中输入一个ll命令,ll就是bash的子进程,bash就是ll的父进程
四、控制进程状态相关指令:
常用的控制进程的指令:
kill [ID] / [名称] [PID]
我们也可以通过 kill -l 这条指令来查看控制进程状态相关的指令
五、僵尸进程与孤儿进程:
进程资源回收概念:
当一个子进程结束运行的时候,它对应的PCB会保留一段时间让其父进程或者操作系统去读取,然后由它对应的父进程或者操作系统去对它占用的资源和空间进行回收的(一般都是父进程去进行此操作)。进程本身是无法对自己进行回收操作的。
1、僵尸进程:
概念:
当一个子进程结束运行后,它的父进程却没有对它进行回收,从而释放子进程占用的资源,那这个子进程就会成为一个僵尸进程。
危害:
僵尸进程在进程表中仍占有一个位置,尽管它占用的内存空间很少,但如果僵尸进程数量过多,可能会导致系统资源耗尽,内存泄漏,甚至造成系统瘫痪等。
常见产生原因:
- 父进程忽略子进程的退出信号,或者由于编程错误未能正确处理。
- 父进程长时间运行或者进入死循环
- 网络编程中的错误处理不当等
以如下代码为例演示:
cpp
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t Child_process = fork(); // 创建一个子进程
while(1)
{
if(Child_process == 0)
{
printf("子进程: pid: %d,ppid: %d\n",getpid(),getppid());
sleep(1);
}
else if(Child_process > 0)
{
printf("父进程: pid: %d,ppid: %d\n",getpid(),getppid());
sleep(1);
}
}
return 0;
}
2、孤儿进程:
概念:
当一个子进程的父进程已经终止,但自身还在运行的进程就称为孤儿进程,当出现孤儿进程时,内核会将孤儿进程交给1号进程(操作系统)管理,就是将其的父进程设为1号进程,以确保这些孤儿进程在结束时能够正确地释放资源,避免其成为僵尸进程。
还是用上面的代码为例:
六、进程的优先级:
操作系统针对进程管理制定了一套规则,以确保进程能够被CPU合理调度,从而维持操作系统的正常运行。
概念:
进程的优先级就是操作系统为进程分配CPU资源时的优先顺序,它决定了进程何时运行以及占用多少CPU时间。每个进程都有一个优先级,这个优先级决定了它在多任务环境中的执行顺序。
在Linux系统下我们可以通过 ps -lA 命令来查看进程的PRI值与NI值(nice值)
PRI值越低,就说明进程的优先级越高,但是PRI值是由操作系统动态产生的,我们无法直接去调整进程的PRI值,但是我们可以通过调整进程的nice值去间接的去调整进程的PRI值。
nice值可以理解为对进程优先级的修正数据,他的取值范围通常为 -20 ~ 19 ,共40个级别。
最终的PRI的计算规则为:新的PRI = 进程默认PRI + nice值
调整nice值:
我们可以通过以下命令来调整进程的nice值
renice [新的nice值] [PID]
这里运行一个简单的死循环程序,并修改其进程优先级:
补充:
1、过高的优先级可能会导致其他进程无法正常运行。确保只在必要时调整优先级,并避免长期保持高优先级状态。
2、在设置进程优先级时,要考虑系统的整体负载情况。如果系统已经处于高负载状态,提高某个进程的优先级可能会加剧资源竞争,导致系统性能下降。
七、进程的四个重要特性:
竞争性:
当多个进程在操作系统中共享有限的系统资源时,它们之间会相互竞争以获取这些资源。每个进程都希望得到更多的CPU时间、内存空间或其他系统资源来执行其任务。因此,进程之间会存在竞争关系。
独立性:
进程是系统中独立运行的基本单位。每个进程都有自己独立的地址空间、数据栈和其他系统资源,它们在运行时互不干扰。即使一个进程崩溃或发生错误,也不会影响其他进程的执行。
并行性:
通常发生在多核或多处理器的系统中,每个处理器核心可以同时执行一个或多个进程。并行执行可以充分利用系统的硬件资源,提高系统的吞吐量和执行效率,使得多个任务可以同时得到处理。
并发性:
指多个进程在一段时间内交替执行,使得每个进程都有机会得到推进。在单处理器系统中,虽然每个时刻只能有一个进程在执行,但通过进程切换的方式,可以确保在一段时间里每一个进程都可以得到运行的机会。并发执行使得系统能够充分利用处理器资源,提高了系统的响应速度和整体性能。
补充:
虽然并发和并行都涉及到多个进程的同时执行,但它们的实现方式和效果是不同的。并行是在物理上同时执行多个进程,而并发则是在逻辑上同时执行多个进程,通过时间片轮转等方式实现交替执行。
八、环境变量:
概念:
是在操作系统中用来指定操作系统运行环境的一些参数,如临时文件夹位置和系统文件夹位置等。环境变量是系统维护的一个全局变量表,以供系统进程访问,通常包括变量名和值(路径),用来指明操作系统的重要目录的路径。一些程序据此确定在哪里放置文件、读取必要信息。
举个"栗子"来讲:
在Linux命令行中如果要运行一个可执行程序(例如我上面写的一个死循环程序,名字为Test),就要输入命令:./Test,需要指定文件路径,需要知道此程序在哪个位置,才能去执行, 但是呢,我们却可以直接使用Linux中的一些基础命令(这些命令的本质也是一个二进制的可执行程序),例如:ll、pwd等、那为什么我们在使用这些命令的时候不用去指定路径呢?
这是因为这些命令有配置环境变量[PATH] ,而[PATH]变量里面记录着指令的位置,当我们执行指令时,操作系统就会通过[PATH]变量里记录的路径去查找该指令的位置,然后执行,当[PATH]变量没有记录我们输入的指令的位置时,就会报错:command not found
配置环境变量:
当我们想执行自己写的程序又不想指定路径时就可以手动去配置环境变量。
我们一般常用以下命令来配置环境变量,需要注意的是:这种方式只对当前shell生效,**具有临时性,**关闭shell后会还原[PATH]。(简单来说就是重启系统会还原)
export PATH=$PATH:[文件路径]
echo $PATH 这条命令为查看当前[PATH]变量中已被写入的路径,冒号[ : ]为分隔符,一边为一个路径