【Linux系统】第十节—【进程概念】环境变量 | 详解,包会!

Hello,我是云边有个稻草人---csdn个人主页,与你分享Linux领域专业知识,今天继续学习环境变量。

《Linux系统》本篇文章所属专栏---持续更新中---欢迎订阅!

目录

四、环境变量

1、概念介绍

【命令行参数】

2、一个例子,一个环境变量

【引入环境变量--->PATH】

【如何理解环境变量呢?存储的角度】

【环境变量,最开始是从哪里来的?】

3、认识更多的环境变量

4、获取环境变量的方法

【命令操作】

【通过代码如何获取环境变量】

5、理解环境变量的特性


正文开始------

【进程概念】相关知识回顾:

【Linux系统】第八节---进程概念(上)---冯诺依曼体系结构+操作系统+进程及进程状态+僵尸进程---详解!-CSDN博客

【Linux系统】第九节---进程状态续集+进程优先级+进程切换-CSDN博客

四、环境变量

1、概念介绍

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

首先了解什么是命令行参数

【命令行参数】

2、一个例子,一个环境变量

【引入环境变量--->PATH】

为什么执行我们自己的的时候要带路径**./** ,而执行系统命令的时候就不需要带**./** ?因为我们创建的程序在当前路径下,而系统命令有环境变量来帮助系统找到对应的命令。

2.1 要执行一个程序,必须先找到它!

2.2 系统中存在环境变量PATH(系统中搜索指令的默认搜索路径),来帮助系统找到目标二进制文件!

/usr/bin 是 Linux 里绝大多数用户日常命令和应用程序的存放地,全是可执行的二进制文件,所有用户都能运行。

是不是将我们自己创建的命令放到 /usr/bin 路径下就可以直接执行了呢?是的,放到这个路径下面系统可以自动就能找到。强烈不建议将我们自己的命令放到该路径下,执行rm /usr/bin/名字 删掉。

为什么系统知道从这个路径下面找到对应的二进制文件呢? 因为环境变量 PATH(系统中搜索指令的默认搜索路径)!PATH下面有/usr/bin 路径,见下:

**env:打印当前系统所有环境变量,格式:名称=内容。**我们使用env确实查到了环境变量PATH,见下:

查看环境变量中具体某一个环境变量:echo $PATH

所以当我们执行 ls 命令时,系统会首先到环境变量PATH下找,按顺序在每个目录下匹配名为ls的可执行文件,找到首个匹配文件就加载运行,遍历全部路径仍未找到,提示 command not found

那是不是将我们自己放命令的路径放到PATH里面是不是系统就可以直接找到我们自己创建的路径呢?是的!

PATH=$PATH:自己存放命令的路径

此时执行自己的程序就可以不带路径了。当我们重新启动Xshell后PATH里面的内容被重置。

【如何理解环境变量呢?存储的角度】

是存储在bash进程的上下文里面的

所以bash内部有两张表!命令行参数表,环境变量表。

但是,如果无人登录,那么环境变量还有没有呢?环境变量在哪里呢?

【环境变量,最开始是从哪里来的?】

系统的相关配置文件里来的!Bash 启动时读取配置文件,通过 malloc 在自身进程内构建环境变量表。

最后,如果Linux系统有10用户登录呢?存在10个bash。

我们开头讲的,执行一个程序,我们必须先找到它,谁找?bash,通过PATH来找(环境变量)。

可以自己梳理一下整个的动态过程。


3、认识更多的环境变量

HOME:指定用户的主工作目录(即用户登陆到Linux系统中时,默认的目录)

如何生成的

用户登录系统、启动 bash 时:系统读取用户信息 + bash 配置文件,自动在bash 进程上下文的环境变量表 中,写入 HOME=xxx 这一条环境变量。

核心作用

  • 直接输入 cd 回车,会自动进入 HOME 指向的家目录;
  • ~ 波浪号,本质就是 HOME 变量的别名~ 等价于 $HOME;
  • 各类软件、配置文件(.bashrc、.bash_profile)默认都存放于 HOME 目录下

SHELL:当前Shell,它的值通常是/bin/bash。

  • bash = 主流默认 Shell,是 CentOS、Ubuntu 等系统默认使用的命令解释器。

  • 记录当前终端使用的命令解释器类型。

  1. USER
  • 含义 :记录当前登录操作的用户名
  • 特点 :切换用户后会同步变化,标识当前正在使用终端的用户。
  1. LOGNAME
  • 含义 :记录最初登录系统的原始用户名
  • 特点 :一旦登录就固定不变,就算用 su 切换别的用户,LOGNAME 依然保留最开始登陆的账号。

su 用户名 临时切换;

su - 用户名 完整登录并加载新用户环境配置

HISTSIZE:

限制当前终端会话(内存中) 能保存的历史命令最大条数

bash 复制代码
history        # 查看所有历史命令
history 10     # 只看最近10条
!数字          # 执行对应编号的历史命令
!!             # 重复执行上一条命令
history | wc -l #用于统计历史命令总行数,通过管道将 history 输出交给 wc -l 计数,结果受 HISTSIZE 限制。

hostname # 查看主机名

hostname 新名字 # 临时修改主机名

SSH_CLIENT=客户端IP 客户端端口 服务器SSH端口

SSH_TTY=/dev/pts/0:标记当前远程登录所使用的终端设备

PWD:记录当前工作目录绝对路径,cd 切换目录会自动更新,存放于 Bash 进程上下文,pwd 命令直接读取该变量。

OLDPWD:记录上一次所在的工作目录绝对路径,由 bash 自动维护,存放在进程上下文的环境变量表。

  • 执行 cd 切换目录 时:原来的 PWD 会自动保存为 OLDPWD,再更新新的 PWD
  • 命令 cd - 本质:直接跳转至 $OLDPWD 目录

cd / cd ~ 依赖环境变量 HOME ,作用:直接进入当前用户家目录 ,二者完全等价。
cd - 依赖环境变量 OLDPWD ,作用:快速切换到上一次的工作目录。


4、获取环境变量的方法

【命令操作】

env、echo $XXX

export :设置⼀个新的环境变量。用于将变量导出到 bash 进程的环境变量表,使其能被子进程继承使用。

unset:删除变量,清空环境变量表中指定内容;与 export 相反,一个导出、一个销毁。

【通过代码如何获取环境变量】

方法一:获取环境变量,命令行第三个参数

理解一下:

bash 复制代码
#include <stdio.h>

// main 函数的第三个参数 env[]
int main(int argc, char *argv[], char *env[])
{
    int i = 0;
    // 循环遍历 env 数组,直到遇到 NULL(结束标记)
    for(; env[i]; i++){
        printf("%s\n", env[i]);
    }
    return 0;
}

编译运行后,会打印出当前进程所有的环境变量,比如:

bash 复制代码
PATH=/usr/local/bin:/usr/bin:/bin
HOME=/home/yourname
USER=yourname
SHELL=/bin/bash
SSH_CLIENT=...

上面代码里面的 env 是一个 字符串指针数组 ,它的每一个元素,都指向一个形如 KEY=VALUE 的环境变量字符串,数组的末尾以 NULL 作为结束标记。

当你在 bash 中运行这个程序时,bash 会把自己进程上下文里的环境变量表 ,完整复制一份,传给这个程序的 env[] 参数。这就是为什么程序能读到 PATHHOMESSH_CLIENT 这些你在 bash 里看到的变量 ------ 它们都是父进程(bash)传给子进程的。

env 数组的最后一个元素是 NULL,当 env[i]NULL 时,条件不成立,循环自动结束。这是 C 语言中遍历以 NULL 结尾的数组的经典写法。

刚才用 export 往bash的环境变量里面导入几个环境变量,那子进程是否能继承我刚才添加的环境变量呢?可以!可以自己使用上面的代码验证一下。

所以,环境变量可以被子进程继承!环境变量是 "父传子、子传孙" 的链式继承关系,每一层子进程都会复制上一层父进程的环境变量,因此可以一直传递下去。所以环境变量在系统当中通常具有全局特性。
虽然变量会层层继承,但每个进程的环境变量都是独立副本,互不影响:

  • 你在子进程 B 里修改 / 删除 MY_VAR,只会影响 B 和它的子进程 C,不会回传给父进程 A
  • 这是典型的 ** 写时复制(Copy-on-Write)** 机制,父进程和子进程的环境变量是完全独立的。

方法二:getenv,根据环境变量的名字来获取环境变量的内容, 找到就返回值的字符串指针 ,找不到返回 NULL

一个有意思的问题,如何使用 getenv 设计一个程序,只能我执行,其他人一律不执行?使用USER!

重新登录一个账号root,发现即使是root也不可以执行该程序正常的执行逻辑

方法三:通过第三⽅变量environ获取

environLinux C 语言的全局变量 ,它直接指向当前进程的整个环境变量表 。它就是 main 函数第三个参数 env \[\] 的真身

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

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

程序运行结果:

推荐第二种,获取具体某一个环境变量 getenv


5、理解环境变量的特性

5.1 环境变量具有全局特性(见上)

5.2 补充两个概念(给后面埋一个伏笔)

a、本地变量

i=10,是设置一个本地变量的操作

为什么 echo $i 能看到,但 env 看不到?

  • 你定义的 i=10 是「局部变量」

    • 直接赋值 i=10(等号两边不能有空格),创建的是 Shell 局部变量
    • 局部变量只存在于当前 Shell 进程内部,只能用 echo $变量名 查看
    • env 命令默认只显示环境变量,所以看不到它
  • env 看不到的根本原因:它没被放进「环境变量表」

    • 只有用 export 导出的变量,才会被写入当前 Shell 的环境变量表
    • env 命令读取的,正是这张表,所以 export 过的变量才会被列出来
  • set:显示环境变量和本地变量

关于本地变量

  • bash会记录两套变量:1、环境变量,2、本地变量
  • 本地变量不会被子进程继承,只会在bash内部被使用!
  • 本地变量就是当前 Shell 的 "私有临时变量",适合做临时数据暂存、脚本内逻辑控制,轻量又安全,不会污染全局环境和子进程。

export 变量名,是已存在的本地变量 ,升级为环境变量,供子进程继承。

b、首先我们要知道:我们的环境变量是在谁里面?bash!

所以,有个问题:export 会将环境变量导入到父进程 Bash 中,但如果 export 是作为子进程执行的,那么按照进程独立性原则,子进程的修改不应该影响父进程,但实际上 export 确实改变了 Bash 的环境变量,这是为什么呢?

因为export是一个内建命令built-in command,内建命令--->不需要创建子进程,而是让bash亲自执行,bash自己调用函数,或者系统调用完成。pwd 也是 Bash 内建命令,只要当前 Bash 进程正常运行,就能执行 pwd 命令获取当前工作目录,不依赖外部可执行文件。

结束,现在再回看一下环境变量的概念就会好理解一点。

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

完------


至此结束------

我是云边有个稻草人

期待与你的下一次相遇!

相关推荐
HLC++10 小时前
Linux的进程间通信
android·linux·服务器
华清远见IT开放实验室12 小时前
实验室建设案例 | 石家庄科技信息职业学院嵌入式实验室——从底层硬件到系统应用,一所应用型高校的嵌入式人才培养这样落地
linux·arm开发·stm32·嵌入式硬件·高校·实验室建设
groundhappy14 小时前
idalib安装和codex ida-mcp配置
linux·开发语言·python
通信小小昕15 小时前
Ubuntu 26.04 中文输入法安装
linux·运维·ubuntu
张小姐的猫16 小时前
【Linux】网络编程 —— HTTP协议(上)
linux·运维·服务器·网络·http·单例模式·策略模式
栩栩云生16 小时前
AI 写代码犯的错,早被写进了错题集
linux·安全·ai编程
imc.1118 小时前
linux基础IO
linux·运维·服务器
BelongPanda19 小时前
Linux Nginx 纯手动 Let‘s Encrypt 泛域名证书配置教程
linux·nginx
酷可达拉斯20 小时前
Linux操作系统-shell编程(0)
linux·运维·服务器·python·云计算
2301_7779983420 小时前
Linux中断机制:操作系统如何高效运行
linux·运维·服务器