白水洋兴达汽修 發表於 2025-9-18 00:00:00

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

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>一、环境变量:系统的&ldquo;运行说明书&rdquo;<ul class="second_class_ul"><li>1. 为什么系统命令不用&ldquo;找路&rdquo;?靠PATH!</li><li>2. 环境变量从哪来?bash&ldquo;读配置&rdquo;来的</li><li>3. 常用环境变量:记这几个就够了</li><li>4. 操作环境变量:3个常用命令</li><li>5. 代码里怎么获取环境变量?3种方法</li><ul class="third_class_ul"><li>方法1:main函数的第三个参数envp</li></ul><li>方法2:getenv函数(推荐!)</li><ul class="third_class_ul"></ul><li>方法3:全局变量environ</li><ul class="third_class_ul"></ul></ul></li><li>二、程序地址空间:不是内存,是&ldquo;虚拟地图&rdquo;<ul class="second_class_ul"><li>1. C程序的地址空间划分</li><ul class="third_class_ul"></ul><li>2. 关键:程序地址空间 &ne; 物理内存</li><ul class="third_class_ul"></ul></ul></li></ul></div><p class="maodian"></p><h2>一、环境变量:系统的&ldquo;运行说明书&rdquo;</h2>
<p>你可以把环境变量理解成Linux系统的&ldquo;小记事本&rdquo;&mdash;&mdash;里面记满了程序运行、系统操作需要的关键信息,比如&ldquo;去哪找你要运行的程序&rdquo;&ldquo;现在登录的是谁&rdquo;&ldquo;当前在哪个文件夹&rdquo;,有了它,系统和程序才知道该&ldquo;怎么干活&rdquo;。</p>
<p class="maodian"></p><h3>1. 为什么系统命令不用&ldquo;找路&rdquo;?靠PATH!</h3>
<p>你有没有好奇过:输入<code>ls</code>&ldquo;列出文件&rdquo;、<code>pwd</code>&ldquo;看当前路径&rdquo;时,为什么不用像自己写的程序那样输全路径(比如<code>/home/xxx/myprogram</code>)?答案就是<strong>PATH环境变量</strong>。</p>
<ul><li>PATH的作用:专门记录&ldquo;程序存放路径&rdquo;的列表。系统执行<code>ls</code>这类命令时,会顺着PATH里的路径挨个找,找到对应的程序文件就运行,找不到就提示&ldquo;命令不存在&rdquo;。</li><li>怎么看PATH?用<code>echo $PATH</code>(注意<code>$</code>是&ldquo;调用环境变量&rdquo;的符号),就像这张图里展示的:</li></ul>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45J52.png" /></p>
<p>图里用<code>echo $PATH</code>输出的一串路径,就是系统找程序的&ldquo;地图&rdquo;。</p>
<ul><li>验证一下:如果把PATH里的路径清空(比如<code>PATH=</code>),再输<code>ls</code>就会提示&ldquo;找不到命令&rdquo;;再用<code>PATH=$PATH:/bin</code>把<code>/bin</code>(<code>ls</code>所在的路径)加回去,<code>ls</code>又能正常用了,就像这张图:</li></ul>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45J39.png" /></p>
<p>如果不小心改坏了PATH也别怕&mdash;&mdash;重启电脑后,系统会重新加载配置,PATH就恢复原样了。</p>
<p class="maodian"></p><h3>2. 环境变量从哪来?bash&ldquo;读配置&rdquo;来的</h3>
<p>每次你登录Linux,系统会启动一个&ldquo;命令解释器&rdquo;&mdash;&mdash;<code>bash</code>(就是你输命令的窗口)。bash不会凭空生成环境变量,而是去读两个关键配置文件:<code>bashrc</code>和<code>profile</code>,从里面加载预设的环境变量。</p>
<ul><li>多用户登录的情况:如果10个用户同时登录Linux,就会启动10个bash,每个bash都会读自己的配置文件,所以每个用户的环境变量可以不一样,就像这张图里的调用关系:</li></ul>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45W49.png" /></p>
<p class="maodian"></p><h3>3. 常用环境变量:记这几个就够了</h3>
<p>除了PATH,还有几个常用的环境变量,用<code>echo $变量名</code>就能查看,对应这张图里的内容:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45VY.png" /></p>
<table><thead><tr><th>环境变量</th><th>作用(通俗说)</th><th>例子</th></tr></thead><tbody><tr><td>USER</td><td>当前登录的用户名</td><td><code>echo $USER</code>&nbsp;输出&nbsp;<code>root</code>&nbsp;或你的用户名</td></tr><tr><td>HISTSIZE</td><td>保存多少条历史命令</td><td>默认存1000条,输过的命令都在这</td></tr><tr><td>HOSTNAME</td><td>这台电脑的&ldquo;名字&rdquo;</td><td><code>echo $HOSTNAME</code>&nbsp;看电脑名</td></tr><tr><td>PWD</td><td>当前所在的文件夹路径</td><td>比如在<code>/home</code>,就输出<code>/home</code></td></tr></tbody></table>
<p>比如这张图里的PWD,就是当前的路径:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45Y52.png" /></p>
<p class="maodian"></p><h3>4. 操作环境变量:3个常用命令</h3>
<p>环境变量分两种:<strong>本地变量</strong>(只有当前bash能用,子进程用不了)和<strong>环境变量</strong>(子进程也能继承),用以下命令切换和操作:</p>
<p><strong>export:把本地变量变成环境变量</strong><br />比如先定义一个本地变量<code>a=123</code>,这时候运行子进程(比如自己写的程序)拿不到<code>a</code>;用<code>export a</code>之后,<code>a</code>就变成环境变量,子进程也能访问了,就像这张图:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45VU.png" /></p>
<p><strong>unset:删除环境变量</strong><br />想删掉某个环境变量,比如<code>a</code>,就输<code>unset a</code>,之后<code>echo $a</code>就看不到值了,对应这张图:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45Y40.png" /></p>
<p><strong>set:查看所有变量</strong><br />输<code>set</code>能看到所有本地变量和环境变量,方便排查问题。</p>
<p class="maodian"></p><h3>5. 代码里怎么获取环境变量?3种方法</h3>
<p>自己写C程序时,想拿到系统的环境变量,有3种常用方法:</p>
<p class="maodian"></p><h4>方法1:main函数的第三个参数envp</h4>
<p>main函数其实能接3个参数(不是只有<code>int main()</code>!),第三个参数<code>envp</code>是个字符串数组,每个元素都是一个环境变量(格式是&ldquo;变量名=值&rdquo;):</p>
<div class="dxycode"><pre class="brush:cpp;">#include&lt;stdio.h&gt;// argc:参数个数,argv:命令行参数,envp:环境变量列表intmain(int argc,char*argv[],char*envp[]){
// 循环打印所有环境变量
int i =0;
while(envp!=NULL){
printf("%s\n", envp);
i++;
}
return0;}</pre></div>
<p>就像这张图里的main函数参数说明:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45Y93.png" /></p>
<p class="maodian"></p><h3>方法2:getenv函数(推荐!)</h3>
<p>想直接拿某个环境变量(比如PATH),用<code>getenv(&quot;变量名&quot;)</code>最方便,返回值就是变量的值:</p>
<div class="dxycode"><pre class="brush:cpp;">#include&lt;stdio.h&gt;#include&lt;stdlib.h&gt;// getenv需要的头文件
intmain(){
// 拿PATH环境变量的值
char*path =getenv("PATH");
// 拿USER环境变量的值
char*user =getenv("USER");
printf("PATH: %s\n", path);
printf("USER: %s\n", user);
return0;}</pre></div>
<p>编译运行后,就能看到PATH和USER的值,对应这张图:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45W59.png" /></p>
<p class="maodian"></p><h3>方法3:全局变量environ</h3>
<p>系统有个全局二级指针<code>environ</code>,专门存环境变量,需要用<code>extern</code>声明后才能用:</p>
<div class="dxycode"><pre class="brush:cpp;">#include&lt;stdio.h&gt;
// 声明全局变量environexternchar**environ;
intmain(){
int i =0;
// 循环打印所有环境变量
while(environ!=NULL){
printf("%s\n", environ);
i++;
}
return0;}</pre></div>
<p>就像这张图里的environ说明:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45b19.png" /></p>
<p class="maodian"></p><h2>二、程序地址空间:不是内存,是&ldquo;虚拟地图&rdquo;</h2>
<p>你写C程序时,可能以为指针指向的是&ldquo;物理内存地址&rdquo;&mdash;&mdash;其实不是!程序里的地址都是&ldquo;虚拟地址&rdquo;,而&ldquo;程序地址空间&rdquo;就是系统给进程画的一张&ldquo;虚拟地图&rdquo;。</p>
<p class="maodian"></p><h3>1. C程序的地址空间划分</h3>
<p>C程序运行时,代码和数据会被分到不同的&ldquo;区域&rdquo;,就像这张图里展示的:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45a43.png" /></p>
<p>用通俗的话解释这几个区域:</p>
<ul><li><strong>代码段</strong>:存你的代码(比如<code>printf</code>、<code>main</code>函数),是&ldquo;只读&rdquo;的&mdash;&mdash;你不能改代码里的内容,比如字符串常量<code>&quot;hello&quot;</code>就存在这,像这张图里说的&ldquo;字符串被编译成代码,只读&rdquo;:</li></ul>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA4595a.png" /></p>
<ul><li>数据段:存全局变量和static变量(比如int g_val = 10;、static int s_val = 20;),程序一启动就分配空间。</li><li>堆:存你手动申请的内存(比如malloc(10)、new int),需要自己free或delete释放。</li><li>栈:存函数里的局部变量(比如int a = 5;),函数结束后自动释放。</li></ul>
<p class="maodian"></p><h3>2. 关键:程序地址空间 &ne; 物理内存</h3>
<p>很多人会把&ldquo;程序地址空间&rdquo;和&ldquo;物理内存&rdquo;搞混,其实它们的关系是:</p>
<ul><li>程序地址空间 = 虚拟地址空间:是系统给进程分配的&ldquo;地址范围&rdquo;(比如0~4GB),进程以为自己独占这部分地址。</li><li>物理内存:电脑里真实的内存条(比如8GB、16GB),系统会把&ldquo;虚拟地址&rdquo;转换成&ldquo;物理地址&rdquo;,再去访问真实内存。</li></ul>
<p>就像这张图里强调的:<strong>C/C++指针用的都是虚拟地址</strong>,程序地址空间是&ldquo;系统概念&rdquo;,不是&ldquo;语言概念&rdquo;:</p>
<p style="text-align:center"><img alt="image.png" src="https://zhuji.jb51.net/uploads/allimg/20250918/2-25091QA45aS.png" /></p>
<p>单说:进程拿着&ldquo;虚拟地址&rdquo;(地图上的位置),系统帮它找到&ldquo;物理地址&rdquo;(真实的房子),这样既能保护内存安全(进程看不到彼此的地址),又能高效利用内存。</p>
<p>以上就是【Linux】环境变量与程序地址空间详解的详细内容,更多相关资料请阅读琼殿技术社区其它文章!</p>
頁: [1]
查看完整版本: Linux环境变量与程序地址空间详解