Linux驱动 2026年4月20日 31 分钟

Linux环境变量相关知识

# Linux 环境变量与交叉编译 ## 1. 什么是环境变量 环境变量本质上就是一组 **键=值** 的配置,例如: …

# Linux 环境变量与交叉编译

## 1. 什么是环境变量

环境变量本质上就是一组 **键=值** 的配置,例如:

“`bash

PATH=/usr/bin:/bin:/opt/gcc-arm/bin

HOME=/home/erhu

LANG=zh_CN.UTF-8

“`

它们的核心作用是:

> **告诉当前 shell 以及它启动出来的子进程,应该在什么环境下运行。**

你可以把它理解成:

– shell 是“父进程”

– `make`、`gcc`、`arm-linux-gnueabihf-gcc` 是它启动的“子进程”

– 父进程会把环境变量传给子进程

所以一旦你在 shell 里设置了环境变量,后面运行的编译器、脚本、构建系统通常都能看到它。

## 2. 环境变量有什么作用

环境变量的作用很广,但你学交叉编译时,最重要的是这几类。

### 2.1 告诉系统“命令去哪里找”—— PATH

例如:

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

“`

作用:

– 当你输入 `arm-linux-gnueabihf-gcc` 时

– shell 会去 `PATH` 里的目录依次查找

– 找到 `/opt/gcc-arm/bin/arm-linux-gnueabihf-gcc` 就执行

所以安装交叉编译器后,最常做的就是把工具链的 `bin/` 加到 `PATH` 中。

### 2.2 告诉构建系统“用哪个工具链”—— ARCH、CROSS_COMPILE

内核编译里很常见:

“`bash

export ARCH=arm

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

作用:

– `ARCH=arm`:告诉内核这是 ARM 平台

– `CROSS_COMPILE=arm-linux-gnueabihf-`:告诉 Makefile 交叉工具前缀是什么

这样内核构建时会去调用:

“`bash

arm-linux-gnueabihf-gcc

arm-linux-gnueabihf-ld

arm-linux-gnueabihf-objcopy

“`

注意:

– `CROSS_COMPILE` 一般是**前缀**

– 真正能不能找到这些命令,还要依赖 `PATH`,或者你把绝对路径直接写进 `CROSS_COMPILE`

例如:

“`bash

export CROSS_COMPILE=/opt/gcc-arm/bin/arm-linux-gnueabihf-

“`

这样即使 `PATH` 没配,也能找到。

### 2.3 告诉程序“库和头文件在哪”—— LD_LIBRARY_PATH、PKG_CONFIG_PATH 等

例如:

– `LD_LIBRARY_PATH`:运行时动态库搜索路径

– `LIBRARY_PATH`:链接时库搜索路径

– `C_INCLUDE_PATH`:头文件搜索路径

– `PKG_CONFIG_PATH`:`pkg-config` 查 `.pc` 文件的路径

这类变量在应用开发中更常见,在内核编译里不如 `PATH`、`ARCH`、`CROSS_COMPILE` 常用。

### 2.4 控制程序行为

比如:

– `HOME`:用户家目录

– `SHELL`:当前使用的 shell

– `TERM`:终端类型

– `LANG` / `LC_ALL`:语言、编码、区域设置

– `EDITOR`:默认编辑器

所以环境变量不仅影响编译,也影响整个命令行环境。

## 3. 为什么装交叉编译器时常改 /etc/profile

因为交叉编译器安装后,系统默认**不知道它在哪里**

比如工具链放在:

“`bash

/opt/gcc-linaro-arm/bin

“`

如果不加到 `PATH`,你输入:

“`bash

arm-linux-gnueabihf-gcc -v

“`

系统可能会提示:

“`bash

command not found

“`

所以很多教程会在 `/etc/profile` 里加:

“`bash

export PATH=/opt/gcc-linaro-arm/bin:$PATH

“`

这样所有用户登录 shell 时都会自动带上这个路径。

## 4. 环境变量是怎么生效的

这里有个很关键的概念。

### 4.1 shell 变量 ≠ 环境变量

例如:

“`bash

MYVAR=123

“`

这只是当前 shell 里的一个普通变量。

如果你执行:

“`bash

export MYVAR

“`

或者直接:

“`bash

export MYVAR=123

“`

它才会变成**环境变量**,并传给子进程。

### 4.2 子进程继承

例如:

“`bash

export CROSS_COMPILE=arm-linux-gnueabihf-

make

“`

执行流程可以理解成:

“`text

bash

 └─ make

     └─ arm-linux-gnueabihf-gcc

“`

因为 `CROSS_COMPILE` 是 export 过的,所以 `make` 能看到,进而调用对应编译器。

## 5. 修改环境变量有哪些方法

下面按“临时 / 永久 / 当前用户 / 全局”来整理。

### 方法 1:命令行临时设置,仅当前 shell 有效

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

export ARCH=arm

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

**特点:**

– 只对当前终端会话有效

– 关闭终端后失效

– 当前 shell 启动的子进程可见

**适用场景:**

– 临时测试

– 不想污染系统环境

– 验证工具链是否可用

**优点:**

– 安全

– 改动小

– 出问题直接关终端就恢复

**缺点:**

– 每次开新终端都要重新设置

### 方法 2:只对某一条命令生效

“`bash

PATH=/opt/gcc-arm/bin:$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

“`

或者:

“`bash

ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make zImage

“`

**特点:**

– 只影响这一次命令

– 不污染当前 shell 后续环境

**适用场景:**

– 最推荐的**项目级**做法

– 特别适合多个工具链并存

**优点:**

– 作用范围最小

– 不容易误用错工具链

– 最适合内核/驱动工程

**缺点:**

– 每次命令都要写一遍

### 方法 3:写入用户自己的 ~/.bashrc

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

export ARCH=arm

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

**特点:**

– 只对当前用户生效

– 一般对交互式 bash shell 有效

– 新开终端后自动生效

**适用场景:**

– 你自己长期使用某个工具链

– 不想影响其他用户

**优点:**

– 常用、方便

– 不需要 root 权限

– 比改 `/etc/profile` 更安全

**缺点:**

– 只对当前用户有效

– 对某些非交互/非 bash 场景不一定生效

应用后通常执行:

“`bash

source ~/.bashrc

“`

### 方法 4:写入 ~/.profile 或 ~/.bash_profile

**特点:**

– 通常用于 login shell

– 用户登录时生效

**与 ~/.bashrc 的区别:**

– `~/.bash_profile` / `~/.profile` 更偏“登录时初始化”

– `~/.bashrc` 更偏“交互式 bash 的配置”

一般经验:

– 命令别名、提示符常放 `.bashrc`

– 登录环境变量常放 `.profile` / `.bash_profile`

### 方法 5:写入 /etc/profile

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

“`

**特点:**

– 系统全局

– 对所有用户的登录 shell 生效

– 需要 root 权限

**适用场景:**

– 机器是专门的开发机

– 所有人都要用这套工具链

**优点:**

– 一次配置,所有用户受益

– 传统教程里很常见

**缺点:**

– 改动范围大

– 配错会影响所有用户

– 不利于多个工具链共存

– 某些非登录 shell、GUI 程序未必按预期生效

**建议:**

如果一定要做全局配置,更推荐用 `/etc/profile.d/xxx.sh`,不要直接改 `/etc/profile`。

### 方法 6:放到 /etc/profile.d/xxx.sh

例如新建:

“`bash

/etc/profile.d/arm-toolchain.sh

“`

内容:

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

“`

**特点:**

– 也是系统全局

– 更模块化

– 通常会被 `/etc/profile` 自动加载

**优点:**

– 管理清晰

– 方便删除/维护

– 比直接改 `/etc/profile` 更规范

**缺点:**

– 仍然是全局生效

– 仍需 root 权限

### 方法 7:写入 /etc/environment

例如:

“`bash

PATH=”/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/gcc-arm/bin”

“`

**特点:**

– 更偏“系统环境变量配置”

– 不是标准 shell 脚本

– 通常由 PAM 在登录时读取

**与 /etc/profile 的区别:**

– `/etc/profile` 是 shell 脚本

– `/etc/environment` 是简单的键值对文件

– 不能像 shell 那样灵活写逻辑

– 一般不写 `export`

– 对 `$PATH` 这种展开支持不如 shell 脚本直观可靠

**适用场景:**

– 设置简单、固定的系统级变量

### 方法 8:写成单独脚本,手动 source

例如建一个:

“`bash

~/env/imx6ull-gcc.sh

“`

内容:

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

export ARCH=arm

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

使用时:

“`bash

source ~/env/imx6ull-gcc.sh

“`

**特点:**

– 很适合项目/平台隔离

– 不改系统全局

**优点:**

– 多套工具链管理最方便

– 适合嵌入式开发

– 切换平台容易

**缺点:**

– 每次要手动 `source`

### 方法 9:systemd 服务里单独设置

如果某个服务要用特定环境变量,可以在 unit 文件里写:

“`ini

[Service]

Environment=”PATH=/opt/gcc-arm/bin:/usr/bin:/bin”

Environment=”MYVAR=123″

EnvironmentFile=/etc/myenv.conf

“`

**特点:**

– 只对这个服务生效

– 和 shell 登录环境是两套体系

**适用场景:**

– 守护进程

– 自动化构建服务

– CI/CD

**与 /etc/profile 的区别:**

– `/etc/profile` 是 shell 登录时读

– systemd 服务默认不会依赖你的 shell 配置

## 6. 这些方法的核心区别

可以从 4 个维度来记:

1. **作用范围**:当前命令 / 当前 shell / 当前用户 / 全系统

2. **是否持久**:临时 / 永久

3. **在哪种场景生效**:登录 shell / 交互 shell / 服务进程

4. **维护风险**:越全局,影响越大

| 方法 | 作用范围 | 是否永久 | 谁能用 | 典型用途 |

|—|—|—|—|—|

| `export VAR=…` | 当前 shell + 子进程 | 否 | 当前终端 | 临时测试 |

| `VAR=… command` | 仅当前命令 | 否 | 当前命令 | 最干净的项目级用法 |

| `~/.bashrc` | 当前用户 | 是 | 当前用户 | 日常开发 |

| `~/.profile` / `~/.bash_profile` | 当前用户登录环境 | 是 | 当前用户 | 登录初始化 |

| `/etc/profile` | 全局 | 是 | 所有用户 | 全局登录环境 |

| `/etc/profile.d/*.sh` | 全局 | 是 | 所有用户 | 更规范的全局配置 |

| `/etc/environment` | 全局系统环境 | 是 | 登录用户/会话 | 简单静态变量 |

| systemd `Environment=` | 单个服务 | 是 | 指定服务 | 服务运行环境 |

## 7. /etc/profile 和 ~/.bashrc 到底区别在哪

这是最容易混淆的地方。

### /etc/profile

– 系统级

– 登录 shell 常读

– 影响所有用户

– 需要 root

### ~/.bashrc

– 用户级

– 当前用户自己的 bash 配置

– 不需要 root

– 新开终端常会生效

所以:

**你自己学开发**:优先 `~/.bashrc`

**整台开发机所有人都要用**:用 `/etc/profile.d/*.sh`

**只想对当前工程生效**:用 `source env.sh` 或 `VAR=… make`

## 8. 对交叉编译器来说,最推荐怎么做

如果是 Linux 内核 / 驱动学习环境,建议按下面优先级:

### 推荐 1:项目级命令传参,最稳

“`bash

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage

“`

如果 PATH 没配,也可以:

“`bash

make ARCH=arm CROSS_COMPILE=/opt/gcc-arm/bin/arm-linux-gnueabihf- zImage

“`

**优点:**

– 不影响系统其他工程

– 不容易误用错编译器

– 适合多个平台并存

### 推荐 2:单独 env 脚本

“`bash

source ~/env/imx6ull.sh

make zImage

“`

内容:

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

export ARCH=arm

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

**优点:**

– 切换开发板方便

– 管理多套工具链清晰

### 推荐 3:只给自己长期使用,放 ~/.bashrc

如果长期只做这一套 ARM 开发,可以放到 `~/.bashrc`。

### 不太推荐:直接改 /etc/profile

除非:

– 这台机器就是专门做该平台开发

– 所有人都用这套工具链

– 你确定不会和其他版本冲突

否则全局改 PATH 很容易埋坑。

## 9. 常见坑

### 9.1 PATH 写反了

通常写:

“`bash

export PATH=/opt/gcc-arm/bin:$PATH

“`

放前面表示优先使用你的工具链。

如果写成:

“`bash

export PATH=$PATH:/opt/gcc-arm/bin

“`

系统可能先找到别的同名工具。

### 9.2 CROSS_COMPILE 少了末尾的 –

正确:

“`bash

export CROSS_COMPILE=arm-linux-gnueabihf-

“`

不是:

“`bash

export CROSS_COMPILE=arm-linux-gnueabihf

“`

因为 Makefile 最终会拼出:

“`bash

$(CROSS_COMPILE)gcc

“`

少了 `-` 就变成:

“`bash

arm-linux-gnueabihfgcc

“`

错了。

### 9.3 改了配置没生效

修改完以后要么:

“`bash

source ~/.bashrc

“`

或者:

“`bash

source /etc/profile

“`

要么重新登录/重开终端。

### 9.4 sudo 下环境变量失效

有些环境变量用 `sudo` 执行时会被清理。

所以编译一般不要动不动用 `sudo`。内核/驱动编译通常普通用户就够了。

### 9.5 把所有平台都塞进全局 PATH

比如同时装:

– `arm-linux-gnueabihf`

– `aarch64-linux-gnu`

– `arm-none-eabi`

全局 PATH 一股脑全加,后面很容易混乱。

更好的做法是:

– 用项目脚本

– 或命令行指定 `CROSS_COMPILE`

## 10. 一句话总结

> **环境变量就是“告诉 shell 和程序应该怎么运行的一组配置”。**

对交叉编译器来说,最关键的就是:

– `PATH`:去哪里找编译器

– `ARCH`:编译哪个架构

– `CROSS_COMPILE`:用哪套交叉工具前缀

而修改环境变量的方法,本质区别在于:

1. **作用范围**:当前命令 / 当前 shell / 当前用户 / 全系统

2. **是否持久**:临时 / 永久

3. **在哪种场景生效**:登录 shell / 交互 shell / 服务进程

4. **维护风险**:越全局,影响越大

## 11. 针对嵌入式 Linux 学习的建议

对于内核、设备树、驱动开发,推荐优先使用以下两种方式:

1. **命令行显式指定**

“`bash

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-

“`

2. **项目专用环境脚本**

“`bash

source ~/env/imx6ull.sh

“`

这样比直接修改 `/etc/profile` 更安全,也更适合多平台开发。

上一篇 驱动环境搭建

今日主要内容 1.windows主机和开发环境文件整理 正点原子的源码分为配置好的和学习用的路径在电脑中的位置分别如下 ...

下一篇 编译内核模块时为什么要先编译内核

# 为什么编译 Linux 内核模块前,通常要先编译一下 Linux 内核 在学习 Linux 驱动开发时,很多教程都会...