由浅入深的了解进程(4)---优先级,命令行参数,环境变量

2024-08-04 09:36:36 浏览数 (2)

1、优先级

1、1、什么是优先级

和生活中的概念其实是差不多的。优先级在进程中的定义是指定进程获得CPU资源的先后顺序。如果换一个视角的话,优先级的本质也就是在操作系统中的进程PCB结构体中的一个变量表示的是优先级的先后,用整形来表示,几个不同的进程相互比较整形的大小就能够实现优先级的概念。数字越小的优先级越高。 优先级 vs 权限。权限问题是决定能不能,但是你有优先级了,也就是说明你已经能够有权限了。 例子: 假如你带着饭卡去食堂排队,这说明什么,你已经拥有饭卡,拥有能够在食堂吃饭的权利,所以你才有等待排队的过程,如果连饭卡都没有的话,那么也就相当于直接没有权限。这个排队的过程其实也能够看作是优先级的过程。

1、2、为什么需要优先级

进程访问的资源(CPU)始终都是有限的,但是系统中的进程大部分情况下都是有较多的。所以由于这种情况的存在是不可避免的,即使是多个CPU也不能直接解决问题,因为当拥有多个CPU的时候,你就会想着起更多的进程,完成更多的操作。 所以优先级是必须要存在的,只有有优先级的概念才能够合理的处理进程,让系统的效率提高。 例子: 就还像是学校食堂一样,如果说学校有一万个学生,难道就要开一万个窗口给每一个学生都是私人的窗口,私人的厨师吗?很显然,几乎没有学校会是这样,如果这样的话也太浪费资源了,类比一下学校的窗口也就像是计算机中的CPU,不可能给你那么多个的,只会存在较少的窗口,让更多的学生(进程)能够按照秩序排队才是解决问题的好方法。 操作系统关于调度和优先级的原则: 分时操作系统,保证基本的公平。如果进程因为长时间不调度,就会造成饥饿问,由于长时间得不到资源。就像是在食堂一样,如果老是有人来插队的话,就会导致后面的人一直排不到队,后面的人就会一直饿着一样,也会产生问题。

1、3、Linux优先级的特点和查看方式

我们想要在Linux系统下查看优先级的话可以通过

代码语言:javascript复制
ps -l:能够显示优先级,不过只能显示当前窗口下的
ps -al:能够显示全部的优先级

UID:代表执行者的身份。 PID:代表进程的代号。 PPID:代表进程是由哪个进程发展衍生而来的,或者说是父进程的代号。 其中的这几个到底是哪一个才是表示的是优先级呢? PRI(priority):进程优先级 NI(nice):进程优先级的修正数据 所以真正的优先级(PRI)=优先级 nice ,这样的话能够实现优先级的同时,还能够实现对于进程优先级的动态修改过程。

那我们能不能够直接进行优先级的调整呢。

代码语言:javascript复制
top
//然后输入r,确定输入PID
//修改NI值

可是为什么我输入的NI数值为100的时候,和我之后查看到的NI的值确实不一样的呢?所以NI值不能随意调整,只能在范围内调整。因为要保证调度的公平! NI可调整的范围是[-20,19]—40个数 每一次调整优先级,都是从80开始的。这也就是为什么,NI的值为19的时候NI为99,改变NI的值为-10的时候,NI的值为70。

2、补充概念

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

3、命令行参数

问题提出:main函数能够含参数? main函数参数可带可不带。

代码语言:javascript复制
int main(int argc, char *argv[])
//其中argc是后面argv数组的元素的个数。

如果带参数的话,这些参数有什么意义?那我们先让这个main函数先把这个字符串打印出来看看,是什么玩意,我们再看看怎么理解这个东西

直接看显示效果的话,main函数的参数表示的含义就是,如果直接执行可执行程序的话,数组长度是1,数组元素表示的就是可执行程序的名称。如果后面加上别的东西的话数组就会变长,其余下标就是后面添加的字符。 我们在命令行中输入的命令行参数,本质上是命令行字符串。第一个表示的是程序的路径和名称,其余后面的叫做和该进程匹配的选项。所以在放进数组的时候是分开存放的。并且这个字符串数组的最后一个元素存放的是NULL,如果想要证明的话也很简单,就报for循环的终止条件改为argv[i]即可,因为C语言中的NULL表示的就是0。

为什么需要main函数能够传两个参数?

如果我们像这样子简单写一下这个myprocess,就能够实现像指令一样的功能,实现多功能。就像是我们平时用的ls的指令一样,我们通过多样的后续的指令,能够实现不同的功能一样,这篇文章中介绍了很多指令的,可以回顾一下。实现了一个程序通过不同的选项实现不同的功能。 所以有命令行参数,本质是为了让程序能够有不同的选项,用来定制不同程序功能,所以才能够实现命令中会携带很多的选项。 谁干的? 当我们定义一个全局变量的时候,虽然子进程在main函数内部才创建,但是这个程序显示的结果,能够展示的是父进程的数据,子进程都能够看到并且访问。

这说明父进程的父进程是bash。这也就说明,命令行中启动的程序,都会变成进程,并且其实还都是bash的子进程。 所以,bash是在命令行语句之前执行的,所以main函数的字符串数组就是bash的功劳,在程序还没运行前,就把命令行语句放在了main函数中,实现上一个讨论的效果。并且由于父进程的数据能够被子进程看到,所以bash存放字符串数组的时候,在子进程中也能够看到到底存了什么在argv[]之中。

4、环境变量

直接看现象的话,就是为什么像是ls或者别的命令明明也是可执行程序,那为什么我们刚刚自己写的myprocess程序还需要在前面加上我们的命令存储的地址,而ls能够直接使用,不需要再表明地址了?

但是ls也能够通过绝对路径来运行

这是为什么呢?这正就是因为Linux系统中存在一些全局的设置,这些全局的设置就是告诉命令行解释器,去哪些路径下去寻找可执行的程序。 PATH就是表示的是环境变量,如果想要打印环境变量中的内容,就需要$PATH。

这些配置在我们登录Linux的时候,就已经加载到bash进程中了(存在于内存中)。 这些地址就是将来bash在执行时候的默认的搜索的路径,必须要先搜索到才能够继续,因为要到CPU中进行解密等操作。如果默认的情况下没有找到的话,就会报错。找到的话就会进行加载和执行程序。 那我们如果也想像系统一样,我们自己写出来的程序也能够直接让bash直接找到并运行的话,我们该怎么做呢?

直接一个复制,让我们写的程序存在于PATH的目录之下就可以了。 则相当于就是我们把我们写的程序安装到Linux系统中了。 除了直接把我们写的程序加到PATH中的指定的目录下,能不能直接加上我们写的程序的目录呢?

代码语言:javascript复制
PATH=/home/qzy/linux_study/jincheng3

这样可以吗?很显然可以是可以,但是当我们除了执行myprocess的时候能够执行,执行别的时候都执行不了了。那这又是为什么呢?因为PATH的内容全被覆盖了,只留下了我们刚刚才添加的部分,那这时我们该怎么办呢?其实不同慌张,因为PATH进程是内存级别的数据,也就是意味着,我们只需要重新的登陆一下系统就能够重新的配置PATH的路径了。 能不能不覆盖,就是添加呢?

这样子就行了,不是覆盖前面的PATH,而是在后面再加上我们需要添加的路径。 那添加成功了,但是此时的PATH是在内存中的,我怎么做能够做到让这样的改变能够一直存在下去呢?即使是重新登录也能够有这样的配置呢?由于PATH一开始不是在内存中的,而是在系统的对应的配置文件中的。所以想要修改得在系统配置文件中修改。

配置文件的位置在哪?

在每一个文件的家目录之下存在着配置文件。

这就是PAHT配置文件存在的位置,我们在这里修改的话,就能够在以后重新登陆的话就不需要再次修改PATH了。

0 人点赞