Linux环境变量
Linux环境变量
- 孤儿进程
- 进程优先级
- 其他概念
- 环境变量
- 感性的理解环境变量
- 常见的环境变量
- 添加环境变量
- 环境变量的组织形式
- 通过代码如何获取环境变量
- 再次理解环境变量
- 命令行参数
孤儿进程
概念:父进程先于子进程结束,这样的子进程就叫做“孤儿进程”;
“孤儿”进程,真的就没有了父进程了吗?
答案是当然不是,当子进程原先的父进程先子进程一步“去”过后,会由os启动领养程序,该子进程会被init进程(也就是os)领养,此时init进程就是子进程的父进程;
那么为什么孤儿进程需要被init领养呢?
回答这个问题,也就是回答,如果不领养孤儿进程会怎么样?
如果没有进程领养孤儿进程的话,在孤儿进程结束后,由于没有父进程接受它的状态码,也就是没有父进程对其所占的空间进行回收,孤儿进程就会一直处于“僵尸”状态,白白的浪费内存,造成内存泄漏,为此为了回收孤儿进程结束过后的空间,os就安排自己充当了孤儿进程的父进程;
下面我们通过一段代码,来演示孤儿进程:
#include<stdio.h> #include<unistd.h>int main(){pid_t id=fork();if(id==0){//childwhile(1){printf("我是子进程,我的pid:%d,我的ppid:%d\n",getpid(),getppid());sleep(1);}}else if(id>0){//fatherint sec=10;while(sec){printf("我是父进程,我的pid:%d,我的ppid:%d,我还有%ds死去!\n",getpid(),getppid(),sec--);sleep(1);}}else{printf("error!\n");}return 0;}
我们可以通过利用ps -axj
命令来查看我们进程的pid和ppid:
此时子进程由原来的前台程序,变为了后台程序,我们可以通过ps命令输出的STAT哪一项来判断,状态带+号的就是前台程序,不带+号的就是后台程序;我们利用Ctrl+c的快捷键杀不死后台程序,但是我们可以利用命令kill -9 pid
或者killall 进程名
这两个命令来杀死进程;
进程优先级
什么是进程优先级:就是那个进程先执行,那么进程后执行;
为什么会有进程优先级?
因为CPU资源有限,为了使每个进程都合理的使用到CPU资源;
怎么使用优先级?
首先我们可以通过命令:ps -al
来查看:
其中修改优先级的公式:PRI=PRI(默认值)+nice;
nice的取值范围:[-20,19];
nice值为什么是这个区间,因为一个进程的优先级必须有个度,不能过高也不能过低,过高或过低都会严重造成CPU资源的分配不合理;
如何修改优先级?
我们可以输入top命令->输入r->输入进程pid->输入nice值;
一般情况下,我们普通用户只能把优先级变大,不能把优先级变小,如果想要变小优先级,我们可以切换成root:
如果想要变小优先级的话,需要切换成root,因为普通用户权限不够;
其他概念
竞争性: 系统进程数目众多,而CPU资源只有少量,甚至1个,所以进程之间是具有竞争属性的。为了高效完成任务,更合理竞争相关资源,便具有了优先级.
独立性: 多进程运行,需要独享各种资源,多进程运行期间互不干扰.
并行: 多个进程在多个CPU下分别,同时进行运行,这称之为并行.
并发: 多个进程在一个CPU下采用进程切换的方式,在一段时间之内,让多个进程都得以推进,称之为并发.
环境变量
概念:环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数
说实话,这官方的概念,我们初学者理解起来比较困难;我来说说我对于这句话的理解吧:
我认为环境变量就是指定os在一些特定情况下该做什么的动态参数;
就比如:os应该把临时文件放在哪里?当我们运行一个程序时,并没有指定该程序的位置时,os应该去哪里寻找这个程序?在我们需要读取当前机器的用户名时,os应该去哪里拿?
我们可以通过设置环境变量,来告诉os,遇到这些情况时,应该去哪里寻找“答案”;
感性的理解环境变量
或许上面的一通概念,并没有让我们理解什么是环境变量,下面我们通过一个例子来更好的理解环境变量:
在Linux环境下,为什么在运行我们自己的可执行程序时需要带上
./
这样的相对路径,或者绝对路径?而在运行诸如:ls、cd、tree、cp等命令时不需要带上它们的路径?我们可不可以让自己的程序也能不带上路径就运行起来呢?
首先当我们在运行一个不带任何路径的程序时,os会去PATH环境变量下,寻找是否含有当前程序,找到了就执行,找不到就报错!而对于我们指定路径的程序,则去指定路径下搜索!
那么PATH环境变量里面到底装的是什么?
我们可以通过命令:echo $PATH
来查看PATH环境变量下的内容:
我们可以发现PATH里面都是一些路径,这些路径以:
作为分隔!
那么我们如何让我们自己的程序像ls等命令一样不用指定路径也能直接使用呢?
如果我们想要想要像:ls、pwd、tree等命令一样使用起来不带路径的话,我么只需要将我们的可执行程序添加到PTAH中任一一条目录下或者将我们的路径追加到PATH环境变量下面;
首先我们来实验一下第一种办法:
1、将我们的可执行程序添加到PATH环境变量下的任意一路径中去,比如我们可以将我们都程序添加到PATH下的/usr/bin/目录下去:
当然如果我们还是按照原来的方式./Code2-22
来运行程序也是可以的:
2、直接将我们当前目录添加到PATH环境变量中去:
首先我们先来演示一种错误的添加方式:
PATH=路径
向上面这种添加方法,虽然我们的程序可以不带路径运行了,但是像ls这些命令就不能运行了,想要运行他们必须带上路径了:
可这终归不是万全之策,在后续的使用上极其不方便!这里主要有两个解决办法:
1、将原来PATH默认的路径重新赋值给PATH
2、重新登录shell就可以了;
既然上面的那种赋值方式不是正确的方式,那么该如何向PATH环境变量里面追加路径呢?
PATH=$PATH:路径
像这样,过后我们不仅可以不带路径的使用我们追加的路径下的可执行程序,同时也不会影响ls等命令的使用:
常见的环境变量
通过上面的例子我们对于环境变量有了一定的理解,接下来我们来看一看一些比较常见的环境变量:
PATH : 指定命令的搜索路径;
HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)
SHELL : 当前Shell,它的值通常是/bin/bash。
USER:当前登录机器的用户;
PWD:当前所在目录;
当然这都是一些比较常见的环境变量,我们如果想要查看所有环境变量的话,我们可以使用命令env
添加环境变量
那么如何添加环境变量?
我们可以通过命令export 环境变量
我们也可以给这个环境变量赋值export 环境变量=100
;
环境变量的组织形式
首先我们知道环境变量是存储的有内容的,那么这些环境变量里面的内容是从哪里来的?
答:环境变量的内容一般是由os从特定的配置文件中读取到的,当我们的os启动完毕过后,os就会读取相关配置文件里面的数据放到环境变量里面;在Linux下环境变量一般都在家目录下的.bashrc和.bash_profile;
这些环境变量也是数据,os也会对这些数据进行管理,os利用一个字符指针数组来维护这个环境变量表
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串;
这个环境变量表的最后一个元素是NULL,以此来表示环境表的长度;
通过代码如何获取环境变量
通过代码环境变量主要有3种方式:
1、通过main函数的参数获取;
我们都知道main函数是可以带参数的,而且最多可以带3个参数,比如:
int main(int argc,char*argv[],char*envp[]);
其中envp就是指向这个环境表的首元素指针,通过envp我们可以获取到环境变量:
下面我们通过代码测试:
2、我们也可以不用main的参数,C语言给我们提供了一个全局的字符指针,用来指向环境表,我们也可以通过这个全局的环境表来访问环境变量,这个全局的字符指针也就是:environ,我们只需要声明一下即可使用:
3、通过getenv函数来获取;
上面的两种方法虽然可行,但是用起来实在是不方便,比如我向访问一下USER这个环境变量,还得我自己去写匹配算法去一个一个寻找,很是麻烦,而是用getenv函数则会省去我们自己写匹配算法查找的过程,我们只需要告诉getenv我们需要获取哪个环境变量即可,getenv就会返回对应环境变量的内容;如果没有找到对应环境变量则返回NULL;
接着我们利用getenv来测试一下:
的确是这样的,为此我们可以利用该函数实现一个只允许ikun使用的pwd命令!
测试代码:
为了保持我们的pwd指令能像系统的pwd指令那样执行,我们需要将我们的代码所形成的可执行程序添加到PATH其中一个默认目录下:
接着我们来使用一下自己的pwd:
再次理解环境变量
环境变量就是内存级的一张环境变量表,这张表由用户登录的时候,os根据用户形成用户自己环境变量表;每个用户的环境变量表都不一样!
环境变量表中的每个元素都有自己的作用和应用场景,有的是用来进行查看当前用户名的,有的是用来进行用户查找的,有的用来记录当前路径的等等……
每一个环境变量都有自己的应用场景;
那么如何理解环境变量是一张内存级的表呢?
你说一个int a=10;double b=20;这样的a、b变量我能理解,那么环境变量为什么说是内存级?
在os启动的时候,os会启动shell程序,然后将自己读取到的环境变量交给shell,当我们在命令行输入export MYPATH=1000
,shell会认为你是在定义一个新的环境变量,然后shell就会去内存找块空间将"MYPATH=1000"这个字符串存起来(或者malloc一块空间),让后将该空间的指针添加到环境变量表里面!这样就完成了新增环境变量!环境变量是可以被子进程继承下去的,而我们启动的程序都是shell的子进程,因此我们的进程是可以拿到shell维护的环境变量表的!
同时我们需要注意一下,export定义的环境变量具有全局性,也就是export定义的环境变量是会进入环境变量表的,也就可以被所有子进程访问,但是没有用export定义的环境变量,是不具有全局性的,这种环境变量不会进入环境表,自然也就无法被子进程访问,只能在Shell本身进程访问!
比如我们现在创建一个本地的环境变量:我们的子进程是访问不到的:
我们再来通过我们的程序获取该变量:
我们的Code2-22作为shell的子进程并没有在从shell上继承下来的环境表中访问到MYPATH
同时我们也可以通过命令env
来验证,该命令env只会显示出全局的环境变量,对于本地环境变量不显示:
我们发现依旧没有结果;
当时我们用set
命令来找到我们设置的本地环境变量,set命令会显示出全局的和本地的环境变量;
如果我们想要清除环境变量的值可以用unset
命令:
命令行参数
上面我们再介绍利用代码获取环境变量的时候,提到了可以利用main函数的参数来获取,其中我们介绍了envp参数,但是argc、argv参数没怎么讲,现在我们就来理解一下这两个参数的意义;
int main(int argc,char*argv[],char*envp[])
,从结构上我们可以看到argv与envp是同一个类型,于是我们可以大胆的猜测一下,argv也可能表示的是一张表!其中argc是这个表的长度!
那么这个表里面有什么呢?我们可以打印出来看看:
我们可以发现argv似乎输出的是们在命令行输入的指令,我们命令行输入的什么,argv就输出什么;
我们现在来剖析一下我们在命令行输入的东西:
你看这和我们ls -a -l
的形式是不是一样的,实际上我们在命令行指令+选项的方式时,shell会读取到这一串字符串,然后以空格作为间隔,将指令和选项存在一张表里面,当Shell为我们的指令创建进程的时候就会将这张表传给子进程!子进程就可以根据选项表现出不同的功能;
因此argv的作用就是可以让我们的程序根据不同的选项执行不同的功能!
相关文章:

Linux环境变量
Linux环境变量孤儿进程进程优先级其他概念环境变量感性的理解环境变量常见的环境变量添加环境变量环境变量的组织形式通过代码如何获取环境变量再次理解环境变量命令行参数孤儿进程 概念:父进程先于子进程结束,这样的子进程就叫做“孤儿进程”; “孤儿”…...
Kotlin-委托、代理和单例对象
委托和代理 实现委托和代理,使用的是by关键字。 这里设计一个场景:假设某个演员被要求唱歌,但是不会唱歌,就委托一个会唱歌的歌手在后台唱歌。 如何实现这个需求,下面就开始直接写代码 首先定义一个唱歌能力接口 int…...
华为OD机试真题Python实现【报数】真题+解题思路+代码(20222023)
报数 题目 一百个人围成一圈,每个人有一个编码编号从一开始到一百。 他们从一开始依次报数,报道M的人自动退出圈圈, 然后下一个人接着从1开始报数一直到剩余人数小于M。 请问最后剩余人在原先的编码为多少? 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Py…...
MacOS:Error message “error:0308010C:digital envelope routines::unsupported“
命令行:export NODE_OPTIONS--openssl-legacy-provider 原帖:https://stackoverflow.com/questions/69692842/error-message-error0308010cdigital-envelope-routinesunsupported...

Java 异常处理,超详细整理,适合新手入门
目录 前言 抛出异常 捕获异常 处理异常 finally块 总结 前言 当Java程序中出现错误或异常时,通常会抛出一个异常。Java的异常处理机制使得我们可以在程序运行过程中捕获这些异常并采取相应的措施,以便程序能够正常运行或者优雅地停止。 抛出异常 在…...

23年了,GOPATH和go.mod 还在冲突!
现在 新配了 go环境 设置了GOROOT,GOPATH ,发现引用别的包会出问题。一直会报 package XX not in GOROOT (xxxx)我的目录:我的开发目录: /home/fate/go_projects/老样子,下面有 /home/fate/go_…...

Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝,无法连接。(极简解决办法)
一、遇到问题。 在需要启动Redis客户端的时候,会发现会报这个错误。报这个错误的原因就是Redis的服务端没有开启,那Redis的客户端是访问不了的 二、解决办法。 1.解决的办法就是要启动服务端,让这个客户端可以访问到。启动服务端最简单不会…...

华为OD机试 - 优雅数组(Python)【2023-Q1 新题】
华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/category_12199275.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 优雅数组 | 华为…...

【概念辨析】数组指针指针数组
目录 一、数组指针 二、指针数组 三、 数组指针的数组名不是二级指针 再来说最关键的:数组指针为什么不是二级指针呢? 代码如下: 四、指针数组的数组名是二级指针 在复习,在考试,在焦虑。 又一次学习到了数组指针和指针…...
python实战应用讲解-【语法基础篇】字典的创建及建模(附示例代码)
目录 创建和使用字典 函数 dict 代码清单4-1列出了创建电话簿数据库的代码。...
华为OD机试真题Python实现【分糖果】真题+解题思路+代码(20222023)
分糖果 题目 小明从糖果盒中随意抓一把糖果 每次小明会取出一半的糖果分给同学们 当糖果不能平均分配时 小明可以从糖果盒中(假设盒中糖果足够)取出一个或放回一个糖果 小明至少需要多少次(取出放回和平均分配均记一次)能将手中糖果分至只剩一颗 🔥🔥🔥🔥🔥👉�…...

视频技术基础知识
一、视频图像基础 像素:图像的基本单元,即一个带有颜色的小块分辨率:图像的大小或尺寸,用像素个数来表示。原始图像分辨率越高,图像就越清晰位深:存储每位像素需要的二进制位数;位深越大&#…...

Windows应用之——设置定时关机
一 概述 本文介绍window设置自动关机的两种方式: cmd指令设置自动关机任务计划程序设置自动关机第三方定时关机软件 二 cmd指令设置自动关机—不推荐 2.1 自动关机-开启(管理员模式下) 依次点击‘“开始”,在“搜索程序和文件”中输入cmd,…...
华为OD机试真题Python实现【 喊七】真题+解题思路+代码(20222023)
喊七 题目 喊 7,是一个传统的聚会游戏, N 个人围成一圈,按顺时针从1 - 7编号, 编号为1的人从1开始喊数, 下一个人喊得数字是上一个人喊得数字+1, 但是当将要喊出数字7的倍数或者含有7的话, 不能喊出,而是要喊过。 假定N个人都没有失误。 当喊道数字k时, 可以统计每…...

国产蓝牙耳机哪个好用?国产好用的蓝牙耳机推荐
现如今,国产蓝牙耳机越来越受到人们关注,国产蓝牙耳机近几年的发展愈发迅猛,配置上相对于非国产蓝牙耳机来说也毫不逊色。那么,国产蓝牙耳机哪个好用?下面,我来给大家推荐几款好用的蓝牙耳机,一…...

JAVA虚拟机JVM之内存模型
内存模型 java 内存模型 很多人将【java 内存结构】与【java 内存模型】傻傻分不清,【java 内存模型】是 Java Memory Model(JMM)的意思。 关于它的权威解释,请参考 https://download.oracle.com/otn-pub/jcp/memory_model-1.0…...

Java线程——常见方法
一、 常见方法 1.1 概述 ① start_vs_run:直接调用run方法并不会启动新的线程 import cn.itcast.n2.util.FileReader; import lombok.extern.slf4j.Slf4j;Slf4j(topic "c.Test") public class Test {public static void main(String[] args) {Thread t…...

机器学习:基于逻辑回归对某银行客户违约预测分析
机器学习:基于逻辑回归对某银行客户违约预测分析 文章目录机器学习:基于逻辑回归对某银行客户违约预测分析一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.逻辑回归2.业务理解3.读取数据4.数据理解5.数据准备6.逻辑回归模型训练7.模型评…...

MySQL数据库常用命令汇总(全网最全)
目录 数据库常用命令 数据库的创建 数据表的操作 表数据的增删查改 分组与函数查询 运算符:数学运算符 连接查询 多表查询 修改语句 删除语句 字符查询like MySQL练习 总结感谢每一个认真阅读我文章的人!!! 重点&…...

Bulletproofs++
1. 引言 前序博客: Bulletproofs: Short Proofs for Confidential Transactions and More学习笔记Bulletproofs 代码解析Bulletproofs: Shorter Proofs for Privacy-Enhanced Distributed Ledger学习笔记Bulletproofs 代码解析 Liam Eagen 2022年3月论文《Bullet…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...

佰力博科技与您探讨热释电测量的几种方法
热释电的测量主要涉及热释电系数的测定,这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中,积分电荷法最为常用,其原理是通过测量在电容器上积累的热释电电荷,从而确定热释电系数…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...

渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...