【Linux:环境变量的理解】
目录
1 Z(zombie)-僵尸进程
2 孤儿进程
3 环境变量
3.1 基本概念
3.2 测试HOME
3.3 和环境变量相关的命令
3.4 环境变量的组织方式
3.5 环境变量通常是具有全局属性的
在讲环境变量之前,我们先把上次遗留知识点给总结了(僵尸进程和孤儿进程)
1 Z(zombie)-僵尸进程
- 僵死状态(Zombies)是一个比较特殊的状态。当进程退出并且父进程(使用wait()系统调用,后面讲) 没有读取到子进程退出的返回代码时就会产生僵死(尸)进程 。
- 僵死进程会以终止状态保持在进程表中,并且会一直在等待父进程读取退出状态代码。
- 所以,只要子进程退出,父进程还在运行,但父进程没有读取子进程状态,子进程进入Z状态。
我们来创建一个僵尸进程的栗子:
1 #include<iostream>2 #include<unistd.h>3 #include<stdio.h>4 using namespace std;5 6 int main()7 {8 pid_t ret= fork();9 if(ret==0)10 {11 while(1)12 {13 //child14 printf("我是一个子进程,pid:%d,ppid;%d\n",getpid(),getppid());15 sleep(1); 16 return 1;17 }18 }19 else20 {21 while(1)22 {23 //parent24 printf("我是一个父进程,pid:%d,ppid;%d\n",getpid(),getppid());25 sleep(1);26 }27 }28 return 0;29 }
当我们查看该进程时:
不难发现子进程已经处于僵尸状态了,那这样子进程不就没法回收了吗?该进程就会一直占有CPU资源,那不就造成了内存泄露了吗,对的。另外僵尸进程是不能够用命令杀掉的(因为已经退出)。
我们总结下僵尸进程的危害:
- 进程的退出状态必须被维持下去,因为他要告诉关心它的进程(父进程),你交给我的任务,我办的怎么样了。可父进程如果一直不读取,那子进程就一直处于Z状态!维护退出状态本身就是要用数据维护,也属于进程基本信息,所以保存在task_struct(PCB)中,换句话说,Z状态一直不退出,PCB一直都要维护!
- 那一个父进程创建了很多子进程,就是不回收,是不是就会造成内存资源的浪费。因为数据结构对象本身就要占用内存,想想C中定义一个结构体变量(对象),是要在内存的某个位置进行开辟空间! 最终会造成内存泄漏!
如何避免我们将放到后面来讲。
2 孤儿进程
父进程如果提前退出,那么子进程后退出,进入Z之后,那该如何处理呢?父进程先退出,子进程就称之为“孤儿进程”孤儿进程被1号init进程领养。
上面我们提到了子进程先退出就是僵尸进程,那么父进程先退出呢?
我们想想,此时父进程会是僵尸状态吗?
答案是不会的,父进程在此时会被他自己的父进程(bash)回收,而它的子进程则会交给1号进程领养,我们可以修改一下代码,让父进程先退出,然后运行:
这时子进程已经被1号进程给领养了,我们想要杀掉该进程就可以用
killall "文件名"
我们不难看出孤儿进程正常情况下是不会有内存泄漏的。
3 环境变量
3.1 基本概念
- 环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。
- 环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。
相信大家在学习Java的时候都应该配置过环境变量,这是大家学习Java的第一步,相信大家在配置环境变量是心里非常疑惑,为啥要配置环境变量呢?接下来我会慢慢为大家解答的。
首先为问大家一个问题:为啥我们Makefile生成了可执行文件后再运行要加上./ ?
不加./就找不到该文件了吗?答案是是的,只有加上了./我们才能够正确定位到我们想要找的位置,但是像我们使用的一些基本命令像:whoami pwd 等等为啥就不用了呢?
这就是我们今天要讲的主题:因为配置了环境变量。
我们可以使用 env 来查看环境变量:
[grm@VM-8-12-centos lesson7]$ env
XDG_SESSION_ID=342794
HOSTNAME=VM-8-12-centos
SHELL=/bin/bash
TERM=xterm
HISTSIZE=3000
SSH_CLIENT=117.172.173.113 7924 22
OLDPWD=/home/grm
SSH_TTY=/dev/pts/0
USER=grm
LD_LIBRARY_PATH=:/home/grm/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
MAIL=/var/spool/mail/root
PWD=/home/grm/lesson7
LANG=en_US.utf8
HOME=/home/grm
SHLVL=2
LOGNAME=grm
SSH_CONNECTION=117.172.173.113 7924 10.0.8.12 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
PROMPT_COMMAND=history -a; history -a; history -a; history -a; printf "\033]0;%s@%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"
XDG_RUNTIME_DIR=/run/user/0
HISTTIMEFORMAT=%F %T
_=/usr/bin/env
不难发现上面出现了很多配置了的环境变量,像:
PATH : 指定命令的搜索路径HOME : 指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)SHELL : 当前Shell,它的值通常是/bin/bash
还有很多,这里就不一一列举了,大家可以在上面找到。
假设我们要查询pwd在哪个目录下,可以用命令:
[grm@VM-8-12-centos lesson7]$ which pwd
/usr/bin/pwd
我们查看一下环境变量的方法:
echo $NAME
例如:
[grm@VM-8-12-centos lesson7]$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
我们很容易验证pwd的绝对路径:
[grm@VM-8-12-centos lesson7]$ ls /usr/bin/pwd
/usr/bin/pwd
那我们是不是只要将我们可执行文件添加到环境变量中就可以不用加./了呢?
我们可以来试试:
添加环境变量的方法:
export PATH=$PATH:程序所在路径
这时我们直接运行hello程序依旧能够跑起来:
假如我们不小心将命令写成了这个样子:
export PATH=程序所在路径
这时我们系统自带的环境变量将被我们新加入的环境变量所覆盖,大家这时也不要担心,我们将XShell关闭后重新打开就好了。
3.2 测试HOME
[grm@VM-8-12-centos lesson7]$ cd ~
[grm@VM-8-12-centos ~]$ pwd
/home/grm
[grm@VM-8-12-centos ~]$ echo $HOME
/home/grm
我们不难发现我们平常用的pwd指令本质上就是将其添加到了环境变量中。
3.3 和环境变量相关的命令
1. echo: 显示某个环境变量值2. export: 设置一个新的环境变量3. env: 显示所有环境变量4. unset: 清除环境变量5. set: 显示本地定义的shell变量和环境变量
我们看下面的命令:
[grm@VM-8-12-centos ~]$ val=20
[grm@VM-8-12-centos ~]$ echo val
val
[grm@VM-8-12-centos ~]$ echo $val
20
下面我们加入的val在环境变量中吗?
我们通过env命令查询后发现没有在环境变量中,这种叫做本地变量,只在Shell内部有效。
要想导入环境变量得用export命令,就像上面我们使用export导入环境变量一样。当我们使用set时就能够看见我们写入的本地变量和环境变量,不过这个命令很少用。
3.4 环境变量的组织方式
大家心中的main函数应该是无参的,因为我们平时写代码从来都不会些main函数的参数。但是实际上main函数1最多是有3个参数的,分别是:int argc, char *argv[], char *env[]
我们可以来看看命令行第3个参数究竟是什么?
我们创建一个测试文件,并向里面写入:
1 #include<iostream>2 using namespace std;3
E> 4 int main(int argc,char* argv[],char* env[])5 {6 for(int i=0;env[i];i++)7 {8 cout<<env[i]<<endl; 9 }10 return 0;11 }
运行后发现:
这不就是我们刚才通过env查到的环境变量吗?对的,其实main函数中第三个参数是一个指针数组,指向的就是环境变量表。
我们也可以通过第三方变量environ获取:
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{extern char **environ;int i = 0;for(; environ[i]; i++){printf("%s\n", environ[i]);}return 0;
}
libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头文件中,所以在使用时 要用extern声明。
我们还可以通过系统调用获取或设置环境变量。这样做的好处是每次寻找环境变量不用每次都遍历环境变量表。
#include <iostream>
#include <cstdlib.h>
int main()
{printf("%s\n", getenv("PATH"));return 0;
}
常用getenv和putenv函数来访问特定的环境变量。
putenv我们放到后面来讲解。
那么char* argv[]又是什么鬼呢?
我们来看一段代码:
1 #include<iostream>2 using namespace std;3 4 int main(int argc, char* argv[],char* env[])5 { 6 for(int i=0;i<argc;i++)7 {8 cout<<argv[i]<<endl;9 }10 }
当我们这样运行时:
不难发现argv[]将我们在命令行上敲出来的选项都打印出来了,这也是我们输入一些命令时(例如:ls )附带一些选项时的原理,为什么当执行不同的选项时结果会是不同的,就是因为当执行不同的选项时将选项的结果都保存到了argv[]中,当执行时就会拿出保存的结果来执行,具体的执行方式我们将放到后面来讲。
3.5 环境变量通常是具有全局属性的
环境变量通常具有全局属性,可以被子进程继承下去.
#include <stdio.h>
#include <stdlib.h>
int main()
{char * env = getenv("MYENV");if(env){printf("%s\n", env);}return 0;
}
- 环境变量本质就是内存级的一张表,这张表在用户登录系统的时候,进行给特定的用户形成属于自己的环境变量表。
- 环境变量中的每一个都有自己的应用场景,有的是按路径查找的,有的是进行身份验证的,有的是进行动态库查找的,有的是用来确定当前路径等等。
- 环境变量的相关数据是从相关的配置文件中读到的,每一个元素都是kv的。
相关文章:

【Linux:环境变量的理解】
目录 1 Z(zombie)-僵尸进程 2 孤儿进程 3 环境变量 3.1 基本概念 3.2 测试HOME 3.3 和环境变量相关的命令 3.4 环境变量的组织方式 3.5 环境变量通常是具有全局属性的 在讲环境变量之前,我们先把上次遗留知识点给总结了(僵尸进程和孤儿进程&…...

python数据类型与数据结构
目录 一、数据类型 1.1变量与常量 1.1.1变量 1.1.2常量 1.2字符串类型 1.3整数与浮点数 1.4List列表 1.5 元组tuple 1.6字典dict 二、字符串格式化 三、数据输入和类型转换 四、简单列表习题练习 一、数据类型 变量类型: 整数int(4字节&#x…...

大数据自学学习技巧?
经常有人说:先别管大数据是什么,现在理解不了没关系,先开始学,等学着学着就明白了,这种学习路线基本是混合的,很难分清楚自己学了这段怎么用在以后项目中,所以会越学越迷茫,但是等你…...

Qt音视频开发22-音频播放QAudioOutput
一、前言 以前一直以为只有Qt5以后才有QAudioOutput播放音频,其实从Qt4.6开始就有,在Qt6中变成了QAudioSink,功能一样。用QAudioOutput播放音频pcm数据极其方便,只需要指定音频播放设备(可能电脑上有多个音频输出设备…...

JavaEE简单示例——Spring的入门程序
简单介绍: 在之前我们简单的介绍了有关于Spring的基础知识,那么现在我们就来一步步的把理论融入到实践中,开始使用这个框架,使用过程也是非常的简单,大致可以分为几个基础的步骤: 1.首先引入Spring的Mave…...
【嵌入式Bluetooth应用开发笔记】第一篇:DBUS概述与蓝牙开发小试牛刀
DBUS概述 DBus(D-Bus)是一个在不同程序之间传递消息的系统总线。DBus为不同的程序之间提供了一种通信机制,这种通信制可以在不需要知道对方程序的情况下进行通信。 DBus可以使用多种编程语言来开发,包括C、C、Python、Java等。在…...

如何在电脑更换新硬盘后迁移window11系统?2种迁移方法分享!
随着时间的流逝,数据量也在逐渐增多,就会导致您的硬盘空间也变得越来越小,因此系统运行速度可能会受到一些影响而越来越慢。为了摆脱这种情况,您可以选择升级到更大的硬盘来使计算机获取更大的磁盘空间,或者迁移系统到…...
6、Elasticsearch优化
一、Elasticsearch集群配置 1、硬件选择 Elasticsearch的基础是 Lucene ,所有的索引和文档数据是存储在本地的磁盘中, 具体的路径可在 ES 的配置文件 ../config/elasticsearch.yml 中配置,如下:磁盘在现代服务器上通常都是瓶颈。…...

给力|这是一个专业的开源快速开发框架!
在低代码开发市场,专业的开源快速开发框架可以助力企业提升办公协作效率,实现提质增效的办公自动化的发展目标。 流辰信息低代码技术开发平台服务商,拥有丰富的技术经验和案例合作经验,针对不同的客户需求,提供个性化、…...

CIMCAI smart shipping company product container damage identify
世界港航人工智能领军者企业CIMCAI,领先智能航运船公司集装箱管理产品ceaspectusS™全球规模化应用落地智能化航运,全球前三船公司认可验箱标准应用。全球港航人工智能领军者企业CIMCAI,是全球第一家完成两百万次人工智能验箱,上亿…...
ego微商小程序项目-接口测试
文章目录 1.接口理论回顾1.1 接口测试相关概念1.2 接口测试流程2.接口测试文档2.1 接口测试文档基础2.2 ego微商小程序的接口文档解析3.设计接口测试用例3.1 接口测试用例基础3.2 ego微商小程序接口测试用例4. 执行测试用例4.1 ego小程序测试用例执行4.1.1 首页-轮播图4.1.2 用…...
excel文件已经损坏怎么办
1. excel文件突然损坏怎么办Excel修复不成功还可以尝试其他修复方式。1、Excel提示文件已损坏可能是受保护视图的问题。如果打开文件碰到此提示,可以先点确定。在按以下步骤操作:1)在空白程序界面,点击功能栏的【文件】࿰…...

Java【数据结构入门OJ题33道】——力扣刷题记录1
文章目录第一天存在重复元素最大子数组和第二天两数之和合并两个有序数组第三天两个数组的交集买卖股票最佳时机第四天重塑矩阵杨辉三角第五天有效的数独矩阵置零第六天字符串中第一个唯一字符救赎金第七天判断链表是否有环合并两个有序链表移除链表元素第八天反转链表删除重复…...

Spring事务介绍
文章目录一、编程式事务二、声明式事务(常用)三、事务实战详解3.1)事务的回滚机制3.2)事务的传播3.3)事务超时时间3.4)事务隔离级别3.5)事务回滚条件Spring中对事务有两种支持方式,分…...
Intellij Idea如何使用VM
打开Run/Debug Configuration 然后在More option 里选择 add VM options 根据要实现的目的选择main class 比如说要建造class diagram 那就选择app.ClassDiagramGenerator 然后在下面那行输入 D:\software-engineering\2023\commons-compress\target\classes true true org.apa…...
基础04-什么时候不能使用箭头函数
箭头函数的缺点 题目 什么时候不能使用箭头函数? 箭头函数的缺点 没有 arguments const fn1 () > {console.log(this, arguments) // 报错,arguments is not defined } fn1(100, 200)无法通过 call apply bind 等改变 this const fn1 () >…...

算法小抄5-原地哈希
书接上回,学会了数组中重复数字的解法三,相信接下来的题也难不倒你 找到数组中消失的数字 题目链接 题意 对于一个大小为n的数组,数组中所有的数都在[1,n]内,其中有些数字重复了,由于有些数字重复了,另一些数字就一定会确实,这次需要找到所有缺少的数字并且返回结果 有没有发…...

java零基础入门(1)
java零基础入门一、JRE和JDK1.1 JRE1.2 JDK1.3 IDK,JRE,JVM三者的包含关系二、CMD2.1 打开CMD2.2 常用CMD命令2.2.1 盘符名称 冒号2.2.2 dir2.2.3 cd 目录2.2.4 cd ..2.2.5 cls2.2.6 exit2.2.7 cd \2.2.8 cd \目录\目录\目录\目录2.3 利用快捷cmd打开 Q…...
java socket实例
/*** 启动项目后就创建Server Socket服务*/PostConstructpublic void runServerSocket() {try {ExecutorService executorService Executors.newFixedThreadPool(10);// 创建线程池ServerSocket serverSocket new ServerSocket(9090);// 在设备上配置的服务端监听端口为9090e…...

计算机中信息的表示和处理 整数和小数的二进制表示
信息的表示和处理整数进制字移位运算无符号数和有符号数加法运算小数定点表示IEEE 浮点表示规格化和非规格化舍入浮点运算现代计算机存储和处理的信息以二值信号表示,这些二进制数字称为位,为什么要用二进制来进行编码?因为二进制只有1和0两种…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
是否存在路径(FIFOBB算法)
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...