【Linux】进程优先级 命令行参数 环境变量

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

目录

文章目录

前言

一、进程优先级

1.1、进程优先级的基本概念

1.2、优先级 VS 权限

1.3、为什么要有优先级?

1.4、Linux的优先级的特点 && 查看方式

1.5、PRI and NI

1.6、用top命令更改已存在进程的nice

1.7、其他概念

二、命令行参数

三、环境变量

3.1、基本概念

3.2、常见环境变量

3.3、查看环境变量方法

3.4、有什么方法可以不用带路径,直接就可以运行呢?

强硬的方法:

温柔的方法:

但是我们依然想要将可执行程序myprocess的路径添加到PATH环境变量里?

我们想要我们添加的路径,永久的保存在PATH环境变量里,怎么做呢?

3.5、和环境变量相关的命令

3.6、环境变量的组织方式

3.7、通过代码如何获取环境变量

通过第三方变量environ获取

命令行第三个参数

3.8、通过系统调用获取或设置环境变量

3.9、环境变量通常是具有全局属性的

3.10、内建命令

总结



前言

世上有两种耀眼的光芒,一种是正在升起的太阳,一种是正在努力学习编程的你!一个爱学编程的人。各位看官,我衷心的希望这篇博客能对你们有所帮助,同时也希望各位看官能对我的文章给与点评,希望我们能够携手共同促进进步,在编程的道路上越走越远!


提示:以下是本篇文章正文内容,下面案例可供参考

一、进程优先级

1.1、进程优先级的基本概念

  • 指定进程获取某种资源(如:CPU等)的先后顺序。
  • 优先权高的进程有优先执行权利。配置进程优先权对多任务环境的linux很有用,可以改善系统性能。
  • 还可以把进程运行到指定的CPU上,这样一来,把不重要的进程安排到某个CPU,可以大大改善系统整体性能。
  • Linux中优先级数字越小,优先级越高。

要维护一个进程的优先级:task_struct 进程控制块(是描述进程,里面包含了进程的所有属性) --->     struct ----> 内部字段 ----> (default_proi = 80) + (nice = ??) = proi(新的优先级)。

进程的优先级也是进程控制块中所有属性的一种(是内部字段中的一部分)。

1.2、优先级 VS 权限

权限:是能不能的问题。

优先级:已经能了,我们获取资源的顺序。

1.3、为什么要有优先级?

进程访问的资源(CPU)始终都是有限的,系统中进程大部分情况都是较多的。

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

1.4、Linux的优先级的特点 && 查看方式

  • ps -l:只能查看当前终端(当前所在分频页面)下启动的进程。
  • ps -al:查看所有终端下启动的进程。

我们很容易注意到其中的几个重要信息,有下:

  • UID : 代表执行者的身份
  • PID : 代表这个进程的代号
  • PPID :代表这个进程是由哪个进程发展衍生而来的,亦即父进程的代号
  • PRI :代表这个进程可被执行的优先级,其值越小越早被执行
  • NI :代表这个进程的nice值
  • 每次调整优先级,都是从80开始的
  • nice/renice:可以对一个指定的进程,在启动前或运行时,对进程的优先级做动态调整
  • nice并不能让你任意调整,而是有范围的!若任意调整的话,会打破原则中基本的公平
  •  一个进程的优先级是不能频繁更改的

NI:进程优先级的修正数据,nice值,新的优先级 = 优先级 + nice,达到对于进程优先级动态修改的过程。

nice并不能让你随意调整,而是有范围的。[-20~19]

1.5、PRI and NI

  • PRI也还是比较好理解的,即进程的优先级,或者通俗点说就是程序被CPU执行的先后顺序,此值越小 进程的优先级别越高
  • 那NI呢?就是我们所要说的nice值了,其表示进程可被执行的优先级的修正数值
  • PRI值越小越快被执行,那么加入nice值后,将会使得PRI变为:PRI(new)=PRI(old)+nice
  • 这样,当nice值为负值的时候,那么该程序将会优先级值将变小,即其优先级会变高,则其越快被执行
  • 所以,调整进程优先级,在Linux下,就是调整进程nice值
  • nice其取值范围是-20至19,一共40个级别。

1.6、用top命令更改已存在进程的nice

  • top
  • 进入top后按“r”–>输入进程PID–>输入nice值

1.7、其他概念

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

多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进的方式:
如果这种方式下,进程过多,CPU切换负担过重,那么这些进程会出现卡顿的情况,本质是每一个进程被CPU调度的周期变长了。

二、命令行参数

vim Makefile
myprocess : myprocess.cgcc - o $@ $ ^ -g
.PHONY:clean
clean :rm - f myprocess:%s/testStatus/myprocess/   //:将testStatus改成myprocess
vim myprocess.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>//第一个参数argc代表指针数组中参数的个数有多少  
//第二个参数类型:指针数组,char *指向的是字符串首字符的地址
int main(int argc, char* argv[])
{if (argc != 2){printf("Usage: %s -[a,b,c,d]\n", argv[0]);//下标为0的位置,始终会有元素(./程序名)return 1;}if(strcmp(argv[1], "-a") == 0){printf("this is function1\n");}else if(strcmp(argv[1], "-b") == 0){printf("this is function2\n");}else if(strcmp(argv[1], "-c") == 0){printf("this is function3\n");}else if(strcmp(argv[1], "-d") == 0){printf("this is function4\n");}else{printf("no this function!!\n");}for(int i = 0; i < argc; i++){printf("argv[%d]->%s\n", i, argv[i]);}
}

为什么要有命令行参数:

本质:命令行参数本质是交给我们程序不同的选型,用来定制不同的程序功能。命令行中会携带很多的选项。就像 switch 和 case一样。

命令行解释器(bash)在启动时,会为我们维护一张指针数组表,bash将 ./myprocess -a -b -c -d这条命令,遇到这条命令的空格就分成了 n 个子字符串,将子字符串转换成指针数组表里的元素。

我们再来看接下来的代码:

vim myprocess.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int g_val = 100000;
int main()
{printf("I am father process, pid: %d, ppid: %d, g_val: %d\n", getpid(), getppid(), g_val);sleep(5);pid_t id = fork();if(id == 0){//childwhile(1){printf("I am child process, pid: %d, ppid: %d, g_val: %d\n", getpid(), getppid(), g_val);sleep(1);}}else {// fatherwhile(1){printf("I am father process, pid: %d, ppid: %d, g_val: %d\n", getpid(), getppid(), g_val);sleep(1);}}
}

父进程的数据,默认能被子进程看到并访问。

命令行中启动的程序,都会变成进程,其实都是bash的子进程。

三、环境变量

3.1、基本概念

  • 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
  • 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。

3.2、常见环境变量

  • PATH : 指定命令的搜索路径
  • HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
  • SHELL : 当前Shell,它的值通常是/bin/bash
  • HISTSIZE:默认记录用户输入的最新的1000条的历史命令

3.3、查看环境变量方法

echo $PATH
//显示 PATH 环境变量的内容

3.4、有什么方法可以不用带路径,直接就可以运行呢?

我们自己生成的可执行程序,必须加程序的路径(./)才可以执行;但是Linux中的ls、pwd等这些可执行程序不需要加程序的路径,都可以执行,为什么呢?

Linux中,存在一些全局的设置,表明,告诉命令行解释器,应该去那些路径下,去寻找可执行程序。ls命令的路径是在PATH环境变量当中的,所以执行ls命令,就不用带./

echo $PATH

我们一般执行那个命令的时候,我们的命令行解释器(bash)会先去 PATH 这个环境变量下的所有路径里去找有没有我们对应的可执行程序,如果有,就不用加程序的路径(./)了;如果没有,就得加程序的路径(./)。

强硬的方法:

sudo cp myprocess usr/bin/

我们把我们写的myprocess可执行程序拷贝(安装)到Linux系统里指定的PATH环境变量下的 usr/bin 路径下。

温柔的方法:

把我们写的可执行程序myprocess的路径添加到PATH环境变量里呢?

PATH=/home/song/111/code/lesson

因为PATH是变量,我们可以直接让路径赋值给环境变量,但是我们会把PATH环境变量下的所有路径都给覆盖了,不能这么干。

但是不用担心,因为目前PATH环境变量是我们登录Linux系统的时候,就已经被加载到bash进程当中(内存),现在的环境变量是内存级的(默认我们查到的环境变量是内存级的);实际上环境变量的设置,不仅仅是在内存里,在系统的配置文件里也是有的,我们再重新登录一下Linux系统就可以了。

但是我们依然想要将可执行程序myprocess的路径添加到PATH环境变量里?

PATH=$PATH:/home/song/111/code/lesson

保留原来PATH里的路径,再添加一个路径。

但是这个只是在内存级里设置的,Linux系统重新登录一下,我们添加的路径又会消失。

我们想要我们添加的路径,永久的保存在PATH环境变量里,怎么做呢?

最开始的环境变量不是在内存中,而是默认在系统对应的配置文件中。在登录Linux系统的时候,会创建一个bash进程,系统里的配置文件会被bash进程拷贝一份,所以,我们每次重新登录的时候,PATH下的路径都会回复原样。

系统的配置文件在哪里?

这些配置文件都在属于自己的家目录下。

PATH=$PATH:/home/song/111/code/lesson

我们可以把我们添加的路径,可以通过 PATH=$PATH:/home/song/111/code/lesson它,添加到系统的配置文件中,这样我们每次重新打开Linux系统,我们都可以不带路径(./)来执行可执行程序(myprocess)。

3.5、和环境变量相关的命令

  • echo + $xxx: 显示某个环境变量值
  • export + name=val: 导入一个新的环境变量name
  • env: 显示所有环境变量
  • unset + name: 清除环境变量
  • set: 显示本地定义的shell变量和环境变量

我们导入一个变量 hello=123456 ,但是我们没有写export,我们在所有的环境变量中搜索,并没有找到,但是我们却能够单独把这个变量的内容打印到屏幕上。虽然 hello 变量在环境变量中,但是叫本地变量(身在曹营,心在汉)。

3.6、环境变量的组织方式

每个程序都会收到一张环境变量表,环境变量表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串。

3.7、通过代码如何获取环境变量

通过第三方变量environ获取

#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(int argc, char* argv[])
{// 获取一下环境变量extern char** environ;//声明一下 environfor(int i = 0; environ[i]; i++){printf("env[%d]->%s\n", i, environ[i]);}
}//字符串可以理解为数组,数组名就是数组首元素的地址
//environ[i]:是指针数组里面的元素,元素是环境变量(字符串)的地址,所以元素就是字符串

libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。

命令行第三个参数

#include <stdio.h>
#include <string.h>
#include <unistd.h>int main(int argc, char *argv[], char *env[]){int i = 0;for(; env[i]; i++){printf("%s\n", env[i]);}return 0;}

磁盘中有系统的配置文件,而配置文件里面包含了环境变量;Linux系统登录,会在内存中加载bash进程。bash进程将配置文件(里面包含,环境变量)里的数据拷贝了一份。

环境变量可是很多的,bash内部是如何组织的呢?

bash在启动时,也会为我们维护一张表,这张表是一个指针数组表(char *env[]),这张表指向的内容都是char*的,所以,每当我们有一个环境变量(就是字符串,如:PATH=/usr/bin:/a/b/c/...),环境变量把对应的字符串,从配置文件加载进来,字符串信息就有了,把字符串的地址填到我们的环境变量表里,环境变量表的最后一位以 NULL 结尾。

bash进程启动的时候,默认会给我们子进程形成两张表:argv[]命令行参数表,env[]环境变量表(从OS的配置文件夹来)。bash通过各种方式交给子进程。

3.8、通过系统调用获取或设置环境变量

putenv , 后面讲解

getenv , 根据环境变量名拿到环境变量的内容,本次讲解

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>int main(int argc, char* argv[], char* env[])
{char* path = getenv("PATH");if (path == NULL) return 1;printf("path: %s\n", path);for (int i = 0; env[i]; i++){printf("env[%d]->%s\n", i, env[i]);}fork(); // 能!子进程能获得命令行参数和全局变量   bash(父进程) ---> main(子进程) ---> fork()(创建子进程的子进程)
}

常用getenv和putenv函数来访问特定的环境变量。

3.9、环境变量通常是具有全局属性的

  • 环境变量通常具有全局属性,可以被子进程继承下去
#include <stdio.h>
#include <stdlib.h>int main(){char * env = getenv("MYENV");if(env){printf("%s\n", env);}return 0;}

直接查看,发现没有结果,说明该环境变量根本不存在

  • 导出环境变量   export MYENV="hello world"
  • 再次运行程序,发现结果有了!说明:环境变量是可以被子进程继承下去的!想想为什么?

3.10、内建命令

export myval=111111 
//将导入myval成环境变量
echo $myval  
//也能将环境变量myval的内容打印出来(111111)

那么export命令被命令行解释器(bash)运行的时候,不会创建子进程吗?
如果创建子进程,那么export导出来的环境变量就不应该被bash看到。
因为父进程的数据,默认能被子进程看到并访问,是因为创建子进程的时候,子进程是通过fork()继承的方式,看到父进程的。如果子进程导入了一些环境变量做修改了,父进程是看不到的。

但是,我们这里的父进程是能够看到导入环境变量的内容的,这是怎么回事?

那是因为 export 、echo是内建命令,由父进程(bash)亲自执行,并不会创建子进程。


总结

好了,本篇博客到这里就结束了,如果有更好的观点,请及时留言,我会认真观看并学习。
不积硅步,无以至千里;不积小流,无以成江海。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

伦敦金是合法的吗

作为国际黄金市场的代表&#xff0c;“伦敦金”这一术语频繁出现在各类财经报道与投资者交流之中&#xff0c;其合法性始终是投资者关注的核心问题。本文将以“伦敦金是合法的吗&#xff1f;”为主题&#xff0c;全方位剖析伦敦金在全球范围及中国境内的法律地位和投资环境。 “…

代码随想录算法训练营第四十三天|卡码网52. 携带研究材料(第七期模拟笔试)、518. 零钱兑换 II、377. 组合总和 Ⅳ

卡码网52. 携带研究材料&#xff08;第七期模拟笔试&#xff09; 刷题https://kamacoder.com/problempage.php?pid1052文章讲解https://programmercarl.com/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80%E5%AE%8C%E5%85%A8%E8%83%8C%E5%8C%85.…

MySQL关联查询如何优化

好久不见&#xff0c;关于这篇文章&#xff0c;我也是想了很久&#xff0c;还是决定写一篇文章&#xff0c;有很多同学问过 mysql 相关的问题&#xff0c;其实关联查询如何优化&#xff0c;首先我们要知道关联查询的原理是什么&#xff1f; 左连接 left join SELECT 字段列表…

携程Kar98k/hotelUuidKey算法分析

声明 本文以教学为基准、本文提供的可操作性不得用于任何商业用途和违法违规场景。 本人对任何原因在使用本人中提供的代码和策略时可能对用户自己或他人造成的任何形式的损失和伤害不承担责任。 如有侵权,请联系我进行删除。 这里只是我分析的分析过程,以及一些重要点的记录…

【ARM】DS中Coretex-M处理器的常用寄存器介绍

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 了解ArmDS中Coretex-M处理器的常用寄存器的名称及作用。 2、 问题场景 在对Coretex-M处理器进行开发时&#xff0c;了解常用寄存器的名称及作用&#xff0c;可以&#xff1a; 编写正确的程序: 寄存器是程序员用…

UE4_AI_行为树_行为树快速入门指南

声明&#xff1a;学习笔记。 在 行为树快速入门指南 中&#xff0c;你将学会如何创建一个敌方AI&#xff0c;该AI看到玩家后会做出反应并展开追逐。当玩家离开视线后&#xff0c;AI将在几秒钟后&#xff08;这可根据你的需求进行调整&#xff09;放弃追逐&#xff0c;并在场景中…

使用 Postman 批量发送请求的最佳实践

背景 最近写了几个接口&#xff1a; 获取 books 的接口获取 likes 的接口获取 collections 的接口 但是我还是不放心&#xff0c;因为这些接口到底稳不稳定呢&#xff1f;上线后有没有隐患呢&#xff1f;所以我想做一个批量发送接口模拟~ 但是想要做到批量发送接口&#xf…

考研数学|《基础660》太难了!哪本习题集更适合打基础?

对于基础阶段的学习者来说&#xff0c;推荐使用汤家凤老师的《1800题》。这本题集包含了大量的数学题目&#xff0c;覆盖了考研数学的各个知识点和难度层次。题目设计全面&#xff0c;有助于系统地复习和巩固数学知识。 《1800题》提供了详细的解题思路和答案解析&#xff0c;…

oops-framework框架 之 启动流程(三)

引擎&#xff1a; CocosCreator 3.8.0 环境&#xff1a; Mac Gitee: oops-game-kit 回顾 上篇博客中我们通过 oops-game-kit 模版构建了基础的项目&#xff0c;另外讲解了下assets目录结构和游戏配置文件的基本使用相关&#xff0c;详情内容可参考&#xff1a; oops-framewo…

DevOps工作流程之一:Apipost

随着互联网行业的不断发展&#xff0c;为了提高工作效率&#xff0c;加快软件的交付流程&#xff0c;越来越多企业的选择DevOps工作流程。DevOps旨在通过自动化流程和改善协作&#xff0c;实现软件开发、测试和交付的一体化&#xff0c;从而提高软件交付的质量和速度。而Apipos…

测试面试必备:HTTP请求和响应详解!

一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始&#xff0c;客户端按照指定的格式开始向服务端发送HTTP请求&#xff0c;服务端接收请求后&#xff0c;解析HTTP请求&#xff0c;处理完业务逻辑&#xff0c;最后返回一个HTTP的响应给客户端&#xff0c;HTTP的响应内容同…

wireshark 使用实践

1、打开wireshark软件&#xff0c;选择网卡&#xff0c;开始抓包 2、打开浏览器&#xff0c;访问一个http网站&#xff1a;这里我用 【邵武市博物馆】明弘治十一年&#xff08;1498&#xff09;铜钟_文物资源_福建省文 测试&#xff0c;因为它是http的不是https&#xff0c;方…

【OpenWRT】x86平台安装原版OpenWRT

在当今高度互联的数字化时代&#xff0c;网络设备已经成为我们日常生活和工作中不可或缺的一部分。为了满足不同用户对网络功能的个性化需求&#xff0c;开源社区涌现出了诸多优秀的项目&#xff0c;其中 OpenWrt 便是其中之一。 OpenWrt 是一款专注于为嵌入式设备提供定制化、…

【Leetcode-102.二叉树的层序遍历】

题目详情&#xff1a; 给你二叉树的根节点 root &#xff0c;返回其节点值的 层序遍历 。 &#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;[[3],[9,20],[15,7]]示例…

GPT实战系列-智谱GLM-4的模型调用

GPT实战系列-智谱GLM-4的模型调用 GPT专栏文章&#xff1a; GPT实战系列-实战Qwen通义千问在Cuda 1224G部署方案_通义千问 ptuning-CSDN博客 GPT实战系列-ChatGLM3本地部署CUDA111080Ti显卡24G实战方案 GPT实战系列-Baichuan2本地化部署实战方案 GPT实战系列-让CodeGeeX2帮…

【Java刷题篇】滑动窗口

文章目录 &#x1f4c3;滑动窗口&#x1f4dc;基本概念&#x1f4dc;核心思路 ✍最大连续1的个数 III✍水果成篮 &#x1f4c3;滑动窗口 &#x1f4dc;基本概念 滑动窗口是一种基于双指针的一种思想&#xff0c;两个指针指向的元素之间形成一个窗口。 分类&#xff1a;窗口有…

【物联网】Modbus 协议及应用

Modbus 协议简介 QingHub设计器在设计物联网数据采集时不可避免的需要针对Modbus协议的设备做相关数据采集&#xff0c;这里就我们的实际项目经验分享Modbus协议 简介 Modbus由MODICON公司于1979年开发&#xff0c;是一种工业现场总线协议标准。1996年施耐德公司推出基于以太…

libVLC windows开发环境搭建

1.简介 LibVLC是一个强大的开源库&#xff0c;它构成了VLC媒体播放器的核心部分。 LibVLC提供了一系列的功能接口&#xff0c;使得VLC能够处理流媒体的接入、音频和视频输出、插件管理以及线程系统等核心任务。 跨平台性&#xff1a;VLC作为一个跨平台的多媒体播放器&#x…

Java instanceof

目录 简介 示例 注意事项 应用场景 简介 instanceof 是 Java 的保留关键字也称为类型比较运算符&#xff0c;因为它将实例与类型进行比较它的作用是测试它左边的对象是否是它右边的类的实例&#xff0c;返回 boolean 的数据类型instanceof是Java中的二元运算符&#xff0c…

海外代理IP在跨境电商中的五大应用场景

在我国跨境电商的发展中&#xff0c;海外代理IP的应用日益广泛&#xff0c;它不仅帮助商家成功打入国际市场&#xff0c;还为他们在多变的全球电商竞争中保持优势。下面是海外代理IP在跨境电商中五个关键的应用场景。 1、精准的市场分析 了解目标市场的消费者行为、产品趋势以…