【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两种…...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
Robots.txt 文件
什么是robots.txt? robots.txt 是一个位于网站根目录下的文本文件(如:https://example.com/robots.txt),它用于指导网络爬虫(如搜索引擎的蜘蛛程序)如何抓取该网站的内容。这个文件遵循 Robots…...
NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
DingDing机器人群消息推送
文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人,点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置,详见说明文档 成功后,记录Webhook 2 API文档说明 点击设置说明 查看自…...
