目录
一、进程优先级
是什么
为什么要有?
查看进程优先级
修改进程优先级
二、环境变量
命令行参数
概念
常见环境变量
查看环境变量
配置环境变量
内存级别修改(命令行修改,暂时)
①拷贝到系统路径下
② 路径添加到PATH中
修改配置文件(永久)
和环境变量相关的命令
程序获取环境变量
①第三方变量environ
②命令行参数获取
③系统接口获取
一、进程优先级
是什么
在第一弹中我们提及过操作系统会同时存在多个进程,但是呢,操作系统如何得知应该先调度哪个进程?实际上就得看在每个进程优先级!
所以进程优先级就是指进程获取某种资源的先后顺序,是存在于每个PCB中的内部字段。。
在Linux中,优先级的数字越小,优先级越高!
注意:这里需要区分优先级和权限
- 权限:代表的是能不能获取资源的问题
- 优先级:表示的已经有能力了,但是是获取资源的顺序问题!
为什么要有?
- 操作系统中大多数情况下存在很多的进程,但是系统资源是有限的。
- 操作系统关于调度的原则:分时操作系统,基本的公平,如果进程因为长时间不被调度,就会造成饥饿问题!
查看进程优先级
指令:ps -al 查看当前系统所有的进程
示例:
比较重要的信息
- UID:代表执行者身份
- PID:自身ID
- PPID:父进程ID
- PRI:代表进程的优先级,值越小,越优先
- NI:代表进程的nice值,进程优先级的修正数据
修改进程优先级
进程的新优先级=优先级(默认80开始)+nice值,即:PRI(new)=PRI+nice
这里值得一提的是:nice值是有范围的,一般【-20,19】40个数字
操作步骤:
①输入指令top
②按下r+对应的进程pid
③输入要调整的值
④quit退出
可以看到,上述进程调整后变成了60(80-20),倘若你调整的值是超出nice范围的值,比如调整值为100时,系统默认采用的是范围的上限值19,也就是变成80+19=99。
补充几个小概念:
- 并行:多个进程在多个CPU上同时运行
- 并发:多个进程在同一个CPU上采用进程切换的方式,在一段时间内,让多个进程都得以推进
- 独立性:多进程运行,需要独享各种资源,多进程运行期间互不干扰。。
二、环境变量
命令行参数
关于main函数,想必在一些地方,大家都看到过这样的形式:
int main(int argc,char* argv[])
{
return 0;
}
实际上这些参数是可带可不带的!
- argv[]:指针数组,数组里的每一个元素都是一个个指针,指向的是一个字符串。
- argc:代表的数组元素个数。。
打印数组内容
int main(int argc,char* argv[])
{
int i=0;
for(i=0;i<argc;i++)
{
printf("argv[%d]->:%s\n",i,argv[i]);
}
return 0;
}
可以看到,这个数组里面的内容会根据命令行输入的数据而不同,也就是是实际上这个数组存的的命令行的字符串!
一般情况下,默认第一个位置存的都是路径+可执行程序,后面的位置就是该可执行程序匹配的选项!
那么为什么要有命令行参数呢?
实际上就是因为命令行参数的本质是交给我们程序不同的选项,用来定制不同的程序功能,每一个选项都有对应的功能!
演示演示:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(int argc,char* argv[])
{
if(argc!=2)
{
printf("%s->可用选项有-[a,b,c]\n",argv[0]);
return 0;
}
if(strcmp(argv[1],"-a")==0)
{
printf("this is -a function\n");
return 0;
}
else if(strcmp(argv[1],"-b")==0)
{
printf("this is -b function\n");
return 1;
}
else if(strcmp(argv[1],"-c")==0)
{
printf("this is -c function\n");
return 1;
}
else
printf("no section\n");
return 0;
}
所以说,平时我们所接触到的指令底层都类似于这样实现(如ls),这也再一次说明,指令本质就是一个可执行程序,选项就是该可执行程序不同模块的功能!
问题:命令行参数是由谁传递的?
是父进程bash,在命令行中启动程序,实际上都是bash的子进程。(父进程的数据默认都是能被子进程访问的)
概念
- 环境变量一般☞ 在操作系统中用来指定操作系统运行环境的一些参数。(类似于全局变量)
- Linux中,会存在一些全局的设置,目的就是告诉命令行解释器,应该去哪些路径下寻找可执行程序,所以系统指令执行时不需要带路径,而我们自己的可执行程序需要带路径。
常见环境变量
①PATH:指定命令的搜索路径
②HOME:指定用户的主工作目录
③SHELL:当前Shell,值为/bin/bash
查看环境变量
echo $环境变量名称
示例:
上述所显示的路径就是命令行解释器查找指令的路径,也就是系统指令的位置。 所以对于ls这样的命令,可以不带路径执行,就是因为它是全局的。
问题:如果我们想让我们所写的可执行程序能够像系统指令那样不带路径就能执行,要怎么做?配置即可!
配置环境变量
内存级别修改(命令行修改,暂时)
①拷贝到系统路径下
可以看到当我们将我们的可执行程序配置到系统路径下时,就不需要带路径执行,可以直接在命令行运行我们的程序! (不建议这么干,污染系统)
② 路径添加到PATH中
指令:
PATH=$PATH:自己可执行程序的路径
演示:
注意:以上两种方式,都是内存级别的修改(命令行中的修改),也就是说当你关闭Linux时,这些配置都会消失,并不是永久存在的,要想永久存在,就需要配置系统对应的配置文件!!
为何呢?
最开始的环境变量不是存在于内存中的,而是在系统的配置文件中的,当我们在启动Linux时,系统会创建bash进程,bash进程会读取配置文件中的内容,将其中的环境变量拷贝一份。
修改配置文件(永久)
配置文件: bash_profile,存在于家目录下
我们只需要将自己的可执行程序的路径添加到这个文件中,即可实现永久保留!
这样当你重启系统时,配置的记录就能永久保存!
和环境变量相关的命令
- env:显示所有的环境变量
- echo:打印某个环境变量
- exprot:设置新的环境变量
export 环境变量名=值
注意:
1.export设置的新环境变量是内存级别的,也就给bash进程的,不能永久存在!
2.不加上exprot关键字,直接导入的变量是本地变量!本地变量不能被子进程继承,只在bash中有效
- unset:清楚环境变量
程序获取环境变量
①第三方变量environ
为何能呢?
实际上环境变量的在系统中的组织方式是以一张表的形式进行组织的,环境变量表是一个字符指针数组,每个指针指向的是一个以'\0'结尾的环境字符串变量。
前面有说过,当我们启动Linux系统时,会创建bash进程,同时bash进程会读取磁盘上环境变量的配置文件,并拷贝一份。而bash进程是所有在命令行中启动程序的父进程,父进程的数据,默认能被子进程看到(但不能修改)。所以子进程能看到并访问在bash中的环境变量表,所以能用程序访问。。
小结论:bash进程在启动的时候,默认会给子进程形成两张表,一张是命令行参数表,一张是环境变量表,bash会通过各种方式交给子进程。
命令参数来源于用户输入的命令行,环境变量表来源于系统的配置文件!!
Tip:
对于export,echo这样的指令本质也是可执行程序,在命令行中启动,父进程都是bash,可是父进程的数据是不能被修改的,但是export却能将新的环境变量导入到bash的环境变量表中,是不是矛盾了?
并不是!实际上,在Linux中,80%的命令都是由bash的子进程执行的,也就是在命令行启动的程序,但是像export,echo这样的指令实际上是由bash亲自执行的,并不是bash的子进程,而是内建命令!!所谓内建命令,可以理解为bash中的一个函数!(因为bash也是C语言写)。
②命令行参数获取
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
int main(int argc,char* argv[],char* env[])
{
int i=0;
for(;env[i];i++)
{
printf("env[%d]->%s\n",i,env[i]);
}
}
结果也是一样,可见main函数实际上可以不带参数,也可以带2/3个! 这些参数的值实际都是由bash提供的!继承下来的。
③系统接口获取
- getenv()
#include <stdlib.h>
#include <stdio.h>
int main()
{
char* path=getenv("PATH");
if(path==NULL) return 1;
printf("path:%s\n",path);
return 0;
}
这个系统接口能够获取具体的一个环境变量的内容!
一句话:环境变量具有全局的属性,能够被子进程继承下去!
今天的内容就分享到这里,如果对你有所帮助,欢迎点赞+关注!