【Linux】进程的优先级环境变量

个人主页 : zxctscl
如有转载请先通知

文章目录

  • 1. 前言
  • 2. 进程的优先级
    • 2.1 什么是优先级
    • 2.2 为什么要有优先级
    • 2.3 优先级的查看方式
    • 2.4 对优先级调整
  • 3. 命令行参数
  • 4. 环境变量
    • 4.1 环境变量与配置文件
      • 4.1.1 环境变量初步介绍
      • 4.1.2 配置文件
    • 4.2 更多环境变量
    • 4.3 整体理解环境变量与系统
    • 4.4 环境变量的特性

1. 前言

上一篇在进程中提到了 【Linux】进程状态&&僵尸进程和孤儿进程&&阻塞、挂起和运行,这次来继续来谈进程。

2. 进程的优先级

2.1 什么是优先级

在进程的PCB中存在一个进程的优先级,那么什么是进程的优先级?
进程的优先级就是指定一个进程获取某种资源的顺序。

进程中使用task_struct进程控制块结构体中的内部字段用一个整型prio表示优先级。
Linux中优先级数字越小,优先级越高

比较一下优先级和权限:权限决定一件事能不能做,而有优先级就表示一件事情能做只是代表获取资源的顺序。

2.2 为什么要有优先级

因为进程访问的资源(CPU)时有限的,系统中进程大部分情况都是有较多的。
就像打游戏时候,键盘、鼠标等硬件只有一套,不同的进程本质上对系统硬件资源本来就是通过操作系统方式来实现资源的共享。
更形象就像在下课高峰期,食堂买饭要排队。

操作系统关于调度和优先级的原则:分时操作系统,要保证基本的公平。如果进程因为长时间不被调度,就造成了饥饿问题。

2.3 优先级的查看方式

为了方便查看,先用C语言写测试代码:
Makefile:

  1 myprocess:myprocess.c
  2   gcc -o $@ $^ 
  3 .PHONY:clean
  4 clean:
  5   rm -f myprocess

myprocess.c:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3
  4 int main()
  5 {
  6   while(1)
  7   {
  8     printf("I am a process,pid:%d\n",getpid());
  9     sleep(1);
 10   }
 11 }

在Linux中查看优先级的方式用到命令:

ps -al

在这里插入图片描述
PRI:进程的优先级
NI:进程优先级的修正数据,N是nice值。新的优先级=优先级+nice值,达到对于进程优先级动态修改的过程。
UID : 代表执行者的身份
PID : 代表这个进程的代号
PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号

2.4 对优先级调整

改之前的NI:
在这里插入图片描述

想要对进程优先级调整就想要用到命令:

top

在这里插入图片描述
然后输入:r
在这里插入图片描述

再输入进程的pid:
在这里插入图片描述

最后输入要修改的nice值:
先修改为100:
在这里插入图片描述

再来查看一下这个进程的NI:
在这里插入图片描述
所以说:nice值不能让用户任意调整,而是有范围的,如果随便写就有可能使操作系统调度出现不平衡,必须在可控范围内调整。
nice其取值范围是-20至19,一共40个级别。
在这里插入图片描述

当再想要修改nice值的时候,就不能修改了,普通用户不能频繁修改nice值,把账号先切换为root,再把nice值修改为-10:
此时PRI就变为了70:
在这里插入图片描述
每次调整优先级PRI都是从80开始范围是从60到99

新的优先级=优先级+nice值
一般不推荐用户调整进程的优先级

在这里插入图片描述
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰

并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发。

3. 命令行参数

在C语言中会出现main函数带参的情况。
像:

int main(int argc,char *argv[])
{}

main函数的参数可以带可不带。
这些参数

在Linux里面写一个测试代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3
  4 int main(int argc,char *argv[])
  5 {
  6   int i;
  7   for(i=0;i<argc;i++)
  8   {
  9     printf("argv[%d]->%s\n",i,argv[i]);
 10   }
 11 }

argc表示数组中元素的个数,argv[]是一个指针数组。

如果直接执行程序不带参数,那么默认argv[0]执行的就是执行的程序,而且就是有它一个。
如果带1参数,会自动在将参数变成2个,0号下标指向执行的程序,1号下标就只向这个参数。

在这里插入图片描述

这就是命令行字符串。

在这里插入图片描述

这里的argv是一个变成数组,把命令行字符串以空格为分隔符放在argv里面,下标与输入顺序匹配。再将这些以参数的形式传给了main函数,有几个这样的字符串,那么argc就是几。argv数组最后必须以NULL结尾。

在这里插入图片描述
修改一下代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4
  5 int main(int argc,char *argv[])
  6 {
  7   if(argc!=2)
  8   {
  9     printf("Usage: %s -[a,b,c,d]\n",argv[0]);
 10     return 1;
 11   }
 12
 13   if(strcmp(argv[1],"-a")==0)
 14   {
 15     printf("this is function1\n");
 16   }
 17
 18   else if(strcmp(argv[2],"-b")==0)
 19   {
 20     printf("this is function2\n");
 21   }
 22
 23   else if(strcmp(argv[3],"-c")==0)
 24   {
 25     printf("this is function3\n");
 26   }
 27
 28   else if(strcmp(argv[4],"-d")==0)
 29   {
 30     printf("this is function4\n");
 31   }
 32   else{
 33   printf("no this function\n");
 34   }
 35 }
 36

编译运行一下,发现必须要带选项,那就带上:

在这里插入图片描述
同一个程序可以通过不同的选项来执行同一个程序内的不同的功能。

就像是ls带不同选项,功能不一样:
在这里插入图片描述

命令行参数本质交给我们程序的不同选项,用来定制不同的程序功能。命令中就会携带很多的选项

在这里插入图片描述
写一个父子进程的代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4
  5 int g_val=100000;
  6
  7 int main()
  8 {
  9   printf("I am a father process,pid:%d,ppid:%d,g_val:%d\n",getpid(),getppid(),g_val);
 10   sleep(5);
 11
 12   pid_t id=fork();
 13   if(id==0)
 14   {
 15     while(1)
 16     {
 17      printf("I am a child process,pid:%d,ppid:%d,g_val:%d\n",getpid(),getppid(),g_val);
 18      sleep(1);
 19
 20     }
 21   }
 22   else
 23   {
 24   while(1)
 25   {
 26   printf("I am a father process,pid:%d,ppid:%d,g_val:%d\n",getpid(),getppid(),g_val);
 27   sleep(1);
 28
 29   }
 30 }
 31 }

编译运行:
在这里插入图片描述
发现父进程的数据,默认能被子进程看到并访问。
父进程的ppid是谁的?

再修改一下代码:把创建子进程的代码注释
在这里插入图片描述
再编译运行一下:
发现这个ppid还是24361

在这里插入图片描述

查看一下:
发现它是bash

在这里插入图片描述

当把代码改回之前的:
在这里插入图片描述

然后重新编译运行:发现ppid还是24361,还是bash:
在这里插入图片描述

说明命令行中启动的程序,都会变成进程,其实都是bash的子进程。输入的命令行字符串,默认是输入给父进程bash的。

就像ls,本身也是一个可执行程序,启动它就和启动自己写的程序是一样的
在这里插入图片描述

4. 环境变量

4.1 环境变量与配置文件

4.1.1 环境变量初步介绍

为什么执行自己写的程序时候要带路径:
在这里插入图片描述
而ls就不需要:
在这里插入图片描述
也可以带路径执行:
在这里插入图片描述
这个主要是因为在Linux系统中,存在一些全局的设置,表明,告诉命令行解释器,应该去哪些路径下去寻找可执行程序。

这些设置在PATH里面保存,查看的话就用:

echo $PATH

在这里插入图片描述

系统中很多配置,在我们登录Linux系统的时候,就已经被加载到bash进程中,而bash进程就在内存中。

PATH:环境变量
要打印环境变量的内容用:$PATH

bash在执行命令的时候,想要先找到命令,因为未来要加载。
命令会在对应的路径下找,如果没有找到就报:
在这里插入图片描述
如果找到了就会加载并运行这个程序:
在这里插入图片描述
在这里插入图片描述
如果不加路径来执行myprocess会报:找不到
在这里插入图片描述
如果需要把自己写的程序执行和系统的一样,可以可执行程序添加到bash路径下:
在这里插入图片描述

但是一些命令就不能了,PATH里面就只剩下刚才加的路径:

在这里插入图片描述
因为对环境变量直接赋值,就相当于把环境变量直接覆盖了
自己写的程序到是可以直接运行了:
在这里插入图片描述

直接重新登录就可以了:
此时路径又回来了,刚才设置的环境变量就没有了
在这里插入图片描述
默认我们查到的环境变量是内存级的。

不用覆盖,怎么添加环境变量:
用:

PATH=$PATH:路径

在这里插入图片描述
此时再查看环境变量时候:这个环境变量就有了
在这里插入图片描述
再执行程序的时候带不带路径都可以:
在这里插入图片描述

4.1.2 配置文件

最开始的环境变量不是在内存中,而是在系统对应的配置文件中,用户在登录时候,会创建一个bash进程,此时bash就会读取配置文件,就会把配置文件里面的环境变量在bash里面拷贝一份。
这就是为什么重新登陆的时候之前在PATH加到就不存在了,因为配置文件没有改。

这个配置文件在哪里呢?
切换到家目录下,有与配置文件有关的文件:.bash_profile.bashrc还有/etc/bashrc
在这里插入图片描述

打开.bash_profile
在这里插入图片描述
环境变量默认是在配置文件里面的

打开.bash_profile后把路径加上去:
在这里插入图片描述
此时不加路径也可以运行:
在这里插入图片描述

程序登陆:不加路径还是可以运行
在这里插入图片描述

4.2 更多环境变量

env可以查看其他环境变量
在这里插入图片描述
来看看PWD:
会随着路径变化,把当前路径会记录在PWD的环境变量中:
在这里插入图片描述

系统启动的时候会把改程序的shell运行起来,这就有了命令行解释器:
在这里插入图片描述

曾经输入的命令是记录下来的,不可能全部都记住,HISTSIZE默认记录新的3000条历史命令
在这里插入图片描述
history可以查看历史命令:
在这里插入图片描述
是目前维护历史命令的数目:
在这里插入图片描述
这些环境变量是在用户登陆的时候系统自动加载的:
在这里插入图片描述

在这里插入图片描述
我们可以自己导入环境变量:

export THIS_IS_MY_ENV=value

在这里插入图片描述
此时就存在了这个环境变量:
在这里插入图片描述
取消环境变量:

unset THIS_IS_MY_ENV

此时就查不到了:
在这里插入图片描述
在这里插入图片描述
当加环境变量时候不加export,直接写,不会报错:
也可以查出来
在这里插入图片描述
这种变量叫做本地变量。

4.3 整体理解环境变量与系统

先来写一个获取环境变量的测试代码:

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<string.h>
  4
  5
  6 int main()
  7 {
  8   extern char** environ;
  9   int i;
 10   for(i=0;environ[i];i++)
 11   {
 12     printf("env[%d]->%s\n",i,environ[i]);
 13   }
 14 }

在这里插入图片描述
这些环境变量就是和用env指令查到的一样。
环境变量默认也是可以被子进程拿到的,就说明本身不在子进程里面,而环境变量们默认是在bash内部

解释一下代码:
在这里插入图片描述

在磁盘中:有系统级的配置文件,有全局的也有当前进程的,还包含了环境变量。

在内存中:当有一天我们登陆时,就会在内存中给当前用户创建一个进程,就是bash/shell,登陆的时候把这些配置文件信息就加载到bash内部。
所有环境变量的数据都在bash里面。
环境变量有变量名有变量内容,环境变量的本质就是数据。当启动我们自己的程序时,就会在内存中创建一个子进程./myprocess,而父进程的数据,默认能被子进程看到并访问,环境变量是全局的。

环境变量如此多,那么在bash内部如何组织环境变量?
实际上bash在启动的时候,会维护一张表,这张表是一个指针数组char *env[],指向内容全是char*的。每当有一个环境变量,像PATH=/usr/bin:a/b/c…,也就是字符串,环境变量就可以把对应的字符串从配置文件加载过来,配置信息就有了。把环境变量的地址填到环境变量表里面,这个环境变量就纳入到了bash里面。每一个环境变量都是字符串等于内容,最后在以NULL结尾。

bash进程在启动的时候,默认会给我子进程的两张表:argv[]命令行参数表,env[]环境变量表。bash通过各种方式交给子进程。argv[]命令行参数表来自用户输入的命令行;env[]环境变量表从配置文件来

系统为了方便用户找到环境变量表, 就提供了extern char **environ指针就能被全局看到。就可以用[]来访问指针字符串的内容。
在这里插入图片描述
在这里插入图片描述

还可以在main函数里面加三个参数来获取环境变量:

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 #include<string.h>
    4
    5
    6 int main(int argc,char *argv[],char *env[])
    7 {
    8   int i;
    9   for(i=0;env[i];i++)
   10   {
   11     printf("env[%d]->%s\n",i,env[i]);
   12   }
   13 }

编译运行:
在这里插入图片描述
在这里插入图片描述

exoprt导环境变量本质上就是在env[]环境变量表中找到一个没有被使用的位置,然后把它指向对应的环境变量。导环境变量就是把字符串添加到表里。

4.4 环境变量的特性

环境变量具有系统级的全局属性,因为环境变量本身会被子进程继承
系统刚开始启动时候,启动了bash,bash可以启动很多进程,进程可以继续通过代码创建子进程。但是不管有多少给子进程,bash都能拿到所有子进程对应的环境变量,也就是环境变量具有系统级的全局属性。

系统中还存在getenv,可以根据环境变量直接拿到环境变量的内容,可以单个获取环境变量的内容。
在这里插入图片描述
putenv就是用来导环境变量
在这里插入图片描述

用代码来获取一下:

    1 #include<stdio.h>
    2 #include<unistd.h>
    3 #include<string.h>
    4 #include<stdlib.h>
    5
    6 int main(int argc,char *argv[],char *env[])
    7 {
    8  char *path=getenv("PATH");
    9  if(path==NULL)return 1;
   10  printf("path:%s\n",path);
   11 }

编译运行之后,就可以单独获取PATH一个环境变量了:
在这里插入图片描述
获取环境变量的三种方式:

  1. extern char **environ;
  2. 通过main函数参数
  3. getenv(“path”);

在这里插入图片描述
用export导的环境变量也会创建子进程吗?
在这里插入图片描述
并不是,export导的环境变量不会创建子进程。它是内建命令。
在Linux中百分之八十的美丽都是bash创建子进程执行的。还有一些命令是由bash自己亲自去执行的。bash也是用c语言写的,就相当于在bash里面有个export()函数,直接函数调用就执行export了。

把环境变量先清空:
在这里插入图片描述
再在执行其他命令,能被执行的都是内建命令
在这里插入图片描述

本地变量只在本bash内部有效,无法被子进程继承下去。导成环境变量,此时才能被获取。

有问题请指出,大家一起进步!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/547882.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Shiro整合EhCache缓存(二)

Shiro整合EhCache缓存 1、授权、角色认证1.1、后端接口服务注解1.2、授权-获取角色1.3、授权-获取权限1.4、授权-异常处理1.5、前端页面授权 2、EhCache2.1、Shiro整合EhCache 1、授权、角色认证 用户登录后&#xff0c;需要验证是否具有指定角色指定权限。Shiro也提供了方便的…

企业网络日益突出的难题与SD-WAN解决方案

随着企业规模的迅速扩张和数字化转型的深入推进&#xff0c;企业在全球范围内需要实现总部、分支机构、门店、数据中心、云等地点的网络互联、数据传输和应用加速。SD-WAN作为当今主流解决方案&#xff0c;在网络效率、传输质量、灵活性和成本等方面远远超越传统的互联网、专线…

归并排序详解(附代码)

归并排序 数据科学家每天都在处理算法。 然而&#xff0c;数据科学学科作为一个整体已经发展成为一个不涉及复杂算法实现的角色。 尽管如此&#xff0c;从业者仍然可以从建立对算法的理解和知识库中受益。 在本文中&#xff0c;对排序算法归并排序进行了介绍、解释、评估和实…

高温超导量子干涉仪更具实用价值 政策推动行业研制能力提升

高温超导量子干涉仪更具实用价值 政策推动行业研制能力提升 高温超导量子干涉仪&#xff0c;一种采用临界温度在77K以上高温超导材料制造而成的可对磁场微小变化进行测量的仪器&#xff0c;需要工作在液氮环境中。 超导量子干涉仪&#xff08;SQUID&#xff09;&#xff0c;一种…

面试官:为什么忘记密码要重置而不是告诉你原密码?

这是一个挺有意思的面试题,挺简单的,不知道大家平时在重置密码的时候有没有想过这个问题。回答这个问题其实就一句话:因为服务端也不知道你的原密码是什么。如果知道的话,那就是严重的安全风险问题了。 我们这里来简单分析一下。 做过开发的应该都知道,服务端在保存密码到…

CPLD可运行的最高频率是多少

CPLD可运行的最高频率是多少 AG32 内置CPLD的可运行最高频率 AG32 内置CPLD的可运行最高频率 AG32 MCU 的运行最高频率是248M。而CPLD中没有标准的最高频率。 最大能跑多少MHz&#xff0c;取决于cpld 里的设计。 如果是逻辑电路&#xff0c;则不存在时钟的概念。 如果是时序电路…

在vue和 js 、ts 数据中使用 vue-i18n,切换语言环境时,标签文本实时变化

我的项目需要显示两种语言(中文和英文)&#xff0c;并且我想要切换语言时&#xff0c;页面语言环境会随之改变&#xff0c;目前发现&#xff0c;只能在vue中使用$t(‘’)的方式使用&#xff0c;但是这种方式只能在vue中使用&#xff0c;而我的菜单文件是定义在js中&#xff0c;…

直流充电桩与交流充电桩有哪些区别,如何选最靠谱?

在当今快速发展的电动汽车市场&#xff0c;正确选择充电桩成为了车主们面临的重要问题之一。直流充电桩与交流充电桩区到底有什么区别&#xff1f;哪些方面不同&#xff1f;分别适用场景是什么&#xff1f;不同场景应该怎么选&#xff1f;本文一文为您详解。 一、直流充电桩与交…

ObjectMapper的具体介绍与使用

文章目录 声明一、前言二、ObjectMapper与JSONObject比较1、核心主要有三个部分&#xff1a;依赖包不同 2、ObjectMapper使用概述2.1、工程的pom.xml导包信息2.2、创建案例中的测试对象2.3、对象和JSON相互转化2.3.1、测试代码2.3.2、测试结果展示 2.4、集合和JSON像话转化2.4.…

【让自己的U盘变得与众不同】

文章目录 今日座右铭&#xff1a;在心里种花&#xff0c;人生才不会荒芜。 文章目录 文章目录前言一、准备ICO图标二、插入U盘1.点击新建文本文档-输入代码-点击保存2.将代码文本文档名称修改为autorun.inf在这里插入图片描述3.将图标及代码文本文档放入U盘中在这里插入图片描述…

深度残差收缩网络中,使用 Sigmoid 函数的用意在哪?

在深度残差收缩网络中&#xff0c;使用 Sigmoid 函数将输出归一化到 0 和 1 之间的目的是为了限制输出值的范围&#xff0c;并且使得输出可以被解释为概率。这个 Sigmoid 函数的输出可以被看作是一个置信度或者概率的度量&#xff0c;表示某个事件发生的可能性。 在设置阈值时…

财富池指标--通达信主力建仓免费指标公式源码

主力交易一只个股&#xff0c;一般会经过以下几个阶段&#xff1a;建仓、拉升、出货。那么&#xff0c;怎么判断一只股票正处于主力建仓时期呢&#xff1f; 1、从k线图上来看 个股走势图中&#xff0c;连续出现小阳线的k线图&#xff0c;其成交量持续放量&#xff0c;或者在个…

【学习笔记】rt-thread

任务 创建好任务&#xff0c;不管是动态还是静态创建&#xff0c;任务的状态是init &#xff0c;通过start方法来启动任务&#xff1b;线程大小 设置小了&#xff0c;无法正常工作&#xff1f;显示占空间100% 启动过程 TODO 这是编译器特性&#xff1f; 因为RT-Thread使用编…

【QT+QGIS跨平台编译】181:【QGIS+Qt跨平台编译】—【错误处理:找不到_DEBUGA】

点击查看专栏目录 文章目录 一、找不到_DEBUGA二、原因分析三、错误处理 一、找不到_DEBUGA 报错信息&#xff1a; 二、原因分析 采用了非UNICODE&#xff1a; DEFINES - UNICODE没法识别 _DEBUGA 但可以识别 _DEBUG 三、错误处理 修改 _DEBUGA 为 _DEBUG

Android13 开机时间优化

前言 实际生活当中&#xff0c;针对某些应用场景&#xff0c;对Android启动时间要求比较严格&#xff0c;比如车载&#xff0c;车都开出去几公里了&#xff0c;IVI系统还没起来&#xff0c;这就比较尴尬&#xff0c;所以&#xff0c;优化Android启动时间是一项非常重要的工作。…

windows Nginx上部署若依后台管理登录界面之验证码不显示

大多数情况都是本地电脑Nginx部署正常&#xff0c;服务器Nginx部署验证码不显示。如下图 其实是Nginx配置有问题 server {listen 80;//监听端口server_name 域名或者公网ip等;location / {root D:/dist;//前端包文件路径需要修改index index.html; //不用管try_files …

k8s的service为什么不能ping通?——所有的service都不能ping通吗

点击阅读原文 前提&#xff1a;kube-proxy使用iptables模式 Q service能不能ping通&#xff1f; A: 不能&#xff0c;因为k8s的service禁止了icmp协议 B: 不能&#xff0c;因为clusterIP是一个虚拟IP&#xff0c;只是用于配置netfilter规则&#xff0c;不会实际绑定设备&…

深入理解 C++ 中的 KeyFrame 和 KeyFrame*:对象与指针的选择与管理

本文详细讨论了在 C 编程中 KeyFrame 类及其指针 KeyFrame* 的用法、区别与联系。通过探索两者的内存管理、生命周期及使用场景&#xff0c;本文旨在帮助开发者更好地理解何时以及如何选择使用对象或指针&#xff0c;从而提高代码的效率和安全性。 在 C 中&#xff0c;KeyFrame…

求1000以内正整数的平方根(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>int main() {//初始化变量值&#xff1b;int number 0;int result 0;//提示用户&#xff1b;printf("请输入1000以内求平方根的…

Python 版分布式消息队列 Kafka 实现图片数据传输

1、Kafka 介绍 在使用 Kafka 之前&#xff0c;通常需要先安装和配置 ZooKeeper。ZooKeeper 是 Kafka 的依赖项之一&#xff0c;它用于协调和管理 Kafka 集群的状态。 ZooKeeper 是一个开源的分布式协调服务&#xff0c;它提供了可靠的数据存储和协调机制&#xff0c;用于协调…