当前位置: 首页 > news >正文

【Linux】环境变量与程序地址空间详解

前言:欢迎各位光临本博客,这里小编带你直接手撕Linux程序地址空间,文章并不复杂,愿诸君耐其心性,忘却杂尘,道有所长!!!!

解释_chmod_命令_(3).gif

**🔥个人主页:IF’Maxue-CSDN博客

🎬作者简介:C++研发方向学习者

📖**个人专栏:
《C语言》
《C++深度学习》
《Linux》
《数据结构》
《数学建模》
**

⭐️人生格言:生活是默默的坚持,毅力是永久的享受。不破不立,远方请直行!

文章目录

    • 一、环境变量:系统的“运行说明书”
      • 1. 为什么系统命令不用“找路”?靠PATH!
      • 2. 环境变量从哪来?bash“读配置”来的
      • 3. 常用环境变量:记这几个就够了
      • 4. 操作环境变量:3个常用命令
      • 5. 代码里怎么获取环境变量?3种方法
        • 方法1:main函数的第三个参数envp
        • 方法2:getenv函数(推荐!)
        • 方法3:全局变量environ
    • 二、程序地址空间:不是内存,是“虚拟地图”
      • 1. C程序的地址空间划分
      • 2. 关键:程序地址空间 ≠ 物理内存

一、环境变量:系统的“运行说明书”

你可以把环境变量理解成Linux系统的“小记事本”——里面记满了程序运行、系统操作需要的关键信息,比如“去哪找你要运行的程序”“现在登录的是谁”“当前在哪个文件夹”,有了它,系统和程序才知道该“怎么干活”。

1. 为什么系统命令不用“找路”?靠PATH!

你有没有好奇过:输入ls“列出文件”、pwd“看当前路径”时,为什么不用像自己写的程序那样输全路径(比如/home/xxx/myprogram)?答案就是PATH环境变量

  • PATH的作用:专门记录“程序存放路径”的列表。系统执行ls这类命令时,会顺着PATH里的路径挨个找,找到对应的程序文件就运行,找不到就提示“命令不存在”。
  • 怎么看PATH?用echo $PATH(注意$是“调用环境变量”的符号),就像这张图里展示的:
    image.png
    图里用echo $PATH输出的一串路径,就是系统找程序的“地图”。
  • 验证一下:如果把PATH里的路径清空(比如PATH=),再输ls就会提示“找不到命令”;再用PATH=$PATH:/bin/binls所在的路径)加回去,ls又能正常用了,就像这张图:
    image.png

如果不小心改坏了PATH也别怕——重启电脑后,系统会重新加载配置,PATH就恢复原样了。

2. 环境变量从哪来?bash“读配置”来的

每次你登录Linux,系统会启动一个“命令解释器”——bash(就是你输命令的窗口)。bash不会凭空生成环境变量,而是去读两个关键配置文件:bashrcprofile,从里面加载预设的环境变量。

  • 多用户登录的情况:如果10个用户同时登录Linux,就会启动10个bash,每个bash都会读自己的配置文件,所以每个用户的环境变量可以不一样,就像这张图里的调用关系:
    image.png

3. 常用环境变量:记这几个就够了

除了PATH,还有几个常用的环境变量,用echo $变量名就能查看,对应这张图里的内容:
image.png

环境变量作用(通俗说)例子
USER当前登录的用户名echo $USER 输出 root 或你的用户名
HISTSIZE保存多少条历史命令默认存1000条,输过的命令都在这
HOSTNAME这台电脑的“名字”echo $HOSTNAME 看电脑名
PWD当前所在的文件夹路径比如在/home,就输出/home

比如这张图里的PWD,就是当前的路径:
image.png

4. 操作环境变量:3个常用命令

环境变量分两种:本地变量(只有当前bash能用,子进程用不了)和环境变量(子进程也能继承),用以下命令切换和操作:

  1. export:把本地变量变成环境变量
    比如先定义一个本地变量a=123,这时候运行子进程(比如自己写的程序)拿不到a;用export a之后,a就变成环境变量,子进程也能访问了,就像这张图:
    image.png

  2. unset:删除环境变量
    想删掉某个环境变量,比如a,就输unset a,之后echo $a就看不到值了,对应这张图:
    image.png

  3. set:查看所有变量
    set能看到所有本地变量和环境变量,方便排查问题。

5. 代码里怎么获取环境变量?3种方法

自己写C程序时,想拿到系统的环境变量,有3种常用方法:

方法1:main函数的第三个参数envp

main函数其实能接3个参数(不是只有int main()!),第三个参数envp是个字符串数组,每个元素都是一个环境变量(格式是“变量名=值”):

#include <stdio.h>
// argc:参数个数,argv:命令行参数,envp:环境变量列表
int main(int argc, char *argv[], char *envp[]) {// 循环打印所有环境变量int i = 0;while (envp[i] != NULL) {printf("%s\n", envp[i]);i++;}return 0;
}

就像这张图里的main函数参数说明:
image.png

方法2:getenv函数(推荐!)

想直接拿某个环境变量(比如PATH),用getenv("变量名")最方便,返回值就是变量的值:

#include <stdio.h>
#include <stdlib.h> // getenv需要的头文件int main() {// 拿PATH环境变量的值char *path = getenv("PATH");// 拿USER环境变量的值char *user = getenv("USER");printf("PATH: %s\n", path);printf("USER: %s\n", user);return 0;
}

编译运行后,就能看到PATH和USER的值,对应这张图:
image.png

方法3:全局变量environ

系统有个全局二级指针environ,专门存环境变量,需要用extern声明后才能用:

#include <stdio.h>// 声明全局变量environ
extern char **environ;int main() {int i = 0;// 循环打印所有环境变量while (environ[i] != NULL) {printf("%s\n", environ[i]);i++;}return 0;
}

就像这张图里的environ说明:
image.png

二、程序地址空间:不是内存,是“虚拟地图”

你写C程序时,可能以为指针指向的是“物理内存地址”——其实不是!程序里的地址都是“虚拟地址”,而“程序地址空间”就是系统给进程画的一张“虚拟地图”。

1. C程序的地址空间划分

C程序运行时,代码和数据会被分到不同的“区域”,就像这张图里展示的:
image.png

用通俗的话解释这几个区域:

  • 代码段:存你的代码(比如printfmain函数),是“只读”的——你不能改代码里的内容,比如字符串常量"hello"就存在这,像这张图里说的“字符串被编译成代码,只读”:
    image.png
  • 数据段:存全局变量和static变量(比如int g_val = 10;static int s_val = 20;),程序一启动就分配空间。
  • :存你手动申请的内存(比如malloc(10)new int),需要自己freedelete释放。
  • :存函数里的局部变量(比如int a = 5;),函数结束后自动释放。

2. 关键:程序地址空间 ≠ 物理内存

很多人会把“程序地址空间”和“物理内存”搞混,其实它们的关系是:

  • 程序地址空间 = 虚拟地址空间:是系统给进程分配的“地址范围”(比如0~4GB),进程以为自己独占这部分地址。
  • 物理内存:电脑里真实的内存条(比如8GB、16GB),系统会把“虚拟地址”转换成“物理地址”,再去访问真实内存。

就像这张图里强调的:C/C++指针用的都是虚拟地址,程序地址空间是“系统概念”,不是“语言概念”:
image.png

简单说:进程拿着“虚拟地址”(地图上的位置),系统帮它找到“物理地址”(真实的房子),这样既能保护内存安全(进程看不到彼此的地址),又能高效利用内存。


文章转载自:

http://4YF1q8yG.mjtzk.cn
http://oCv4VUP5.mjtzk.cn
http://haFl1PjR.mjtzk.cn
http://NL98CEjk.mjtzk.cn
http://lLWtE2LZ.mjtzk.cn
http://9xlpEzNd.mjtzk.cn
http://S31lm9AV.mjtzk.cn
http://Aj8SWjJw.mjtzk.cn
http://RneU4hCA.mjtzk.cn
http://JFqbn3Rs.mjtzk.cn
http://MqRITBdd.mjtzk.cn
http://M0ZUw6NX.mjtzk.cn
http://UKQmXhuI.mjtzk.cn
http://lVgPCltQ.mjtzk.cn
http://CJvtZ15o.mjtzk.cn
http://6gNhwpSt.mjtzk.cn
http://mpmOYFpu.mjtzk.cn
http://4ll3bDbX.mjtzk.cn
http://jv6W4tw0.mjtzk.cn
http://wNiIlxgj.mjtzk.cn
http://7PLHM1BL.mjtzk.cn
http://LAme3vSv.mjtzk.cn
http://ZI8PVtF4.mjtzk.cn
http://XDLwoiFL.mjtzk.cn
http://qbjxhm9b.mjtzk.cn
http://tYRSNQ61.mjtzk.cn
http://i2JT7zMv.mjtzk.cn
http://ZKFWDfMZ.mjtzk.cn
http://ha7jSru3.mjtzk.cn
http://CxgrKywC.mjtzk.cn
http://www.dtcms.com/a/366134.html

相关文章:

  • Linux——服务器多线程压缩工具介绍
  • 深入探讨AI三大领域的核心技术、实践方法以及未来发展趋势,结合具体代码示例、流程图和Prompt工程实践,全面展示AI编程的强大能力。
  • Makefile学习笔记 (1)
  • Horse3D游戏引擎研发笔记(九):使用现代图形引擎的元数据管理纹理创建过程(类Unity、Unreal Engine与Godot)
  • vue2 打包生成的js文件过大优化
  • 【iOS】对象复制与属性关键字
  • Linux编程——网络编程(UDP)
  • 当液态玻璃计划遭遇反叛者:一场 iOS 26 界面的暗战
  • 大语言模型推理的幕后英雄:深入解析Prompt Processing工作机制
  • 计算机大数据毕业设计推荐:基于Spark的新能源汽车保有量可视化分析系统
  • 如何轻松地将联系人从 Mac 同步到 iPhone
  • 如何本地编译servicecomb-java-chassis
  • 系统越拆越乱?你可能误解了微服务的本质!
  • 商城源码后端性能优化:JVM 参数调优与内存泄漏排查实战
  • SVN和Git两种版本管理系统对比
  • Clang 编译器:下载安装指南与实用快捷键全解析
  • Java全栈开发面试实录:从基础到微服务的深度探索
  • CentOS系统如何查看当前内存容量
  • SuperSocket 动态协议服务端开发全解析
  • RTSP 协议认证机制详解:Basic 与 Digest 的原理与应用
  • 小迪安全v2023学习笔记(七十七讲)—— 业务设计篇隐私合规检测重定向漏洞资源拒绝服务
  • 【RNN-LSTM-GRU】第四篇 GRU门控循环单元:LSTM的高效替代者与实战指南
  • 为何三折叠手机只有华为可以?看华为Mate XTs非凡大师就知道
  • 2025年09月03日最热门的开源项目(Github)
  • Redis底层实现原理之五大基础结构
  • 云手机与网络游戏相结合的优势?
  • Docker学习笔记(二):镜像与容器管理
  • 20. 云计算-华为云-云服务
  • 域名注册后,为什么还需要域名解析?
  • 嵌入式硬件 - 51单片机3