嵌入式Linux系统编程 — 7.2 进程的环境变量

目录

[1 什么是进程的环境变量](#1 什么是进程的环境变量)

[2 环境变量的作用](#2 环境变量的作用)

[3 应用程序中获取环境变量](#3 应用程序中获取环境变量)

[3.1 environ全局变量](#3.1 environ全局变量)

[3.2 获取指定环境变量 getenv](#3.2 获取指定环境变量 getenv)

[4 添加/删除/修改环境变量](#4 添加/删除/修改环境变量)

[4.1 putenv()函数添加环境变量](#4.1 putenv()函数添加环境变量)

[4.2 setenv()函数](#4.2 setenv()函数)

[4.3 unsetenv()函数](#4.3 unsetenv()函数)


1 什么是进程的环境变量

每一个进程都有一组与其相关的环境变量, 这些环境变量以字符串形式存储在一个字符串数组列表中,把这个数组称为环境列表。 其中每个字符串都是以"名称=值(name=value)" 形式定义,所以环境变量是"名称-值"的成对集合。

譬如在 shell 终端下可以使用 env 命令查看到 shell 进程的所有环境变量,如下所示:

使用 export 命令还可以添加一个新的环境变量或删除一个环境变量:

bash 复制代码
export LINUX_TEST=123456 # 添加 LINUX_TEST 环境变量

使用"export -n LINUX_TEST"命令则可以删除 LINUX_TEST 环境变量。

2 环境变量的作用

环境变量主要有以下几个作用:

  • 配置应用程序:环境变量可以用于存储应用程序的配置信息,如文件路径、配置选项等。这使得应用程序可以在不同的环境中使用相同的代码,但根据环境变量的不同而表现出不同的行为。

  • 传递信息 :在进程创建时,父进程的环境变量可以传递给子进程。这允许在不同程序之间共享信息,例如,用户的家目录路径通常通过环境变量 HOME 传递。

  • 控制shell行为:在shell中,环境变量控制着许多行为,如提示符的格式、别名、shell脚本的搜索路径等。

3 应用程序中获取环境变量

3.1 environ全局变量

应用程序当中也可以获取当前进程的环境变量,事实上,进程的环境变量是从其父进程中继承过来的,譬如在 shell 终端下执行一个应用程序,那么该进程的环境变量就是从其父进程(shell 进程)中继承过来的。新的进程在创建之前,会继承其父进程的环境变量副本。

环境变量存放在一个字符串数组中,在应用程序中,通过 environ 变量指向它, environ 是一个全局变量,在我们的应用程序中只需申明它即可使用,如下所示:

bash 复制代码
extern char **environ; // 申明外部全局变量 environ

编写应用程序,获取进程的所有环境变量。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

extern char **environ;

int main() 
{
    // 遍历环境变量数组
    while (*environ != NULL) {
        printf("%s\n", *environ);
        environ++;
    }

    return 0;
}

运行结果如下,可以看到和'evn'命令行有相同的结果。

3.2 获取指定环境变量 getenv

如果只想要获取某个指定的环境变量,可以使用库函数 getenv(),其函数原型如下所示:

cpp 复制代码
#include <stdlib.h>

char *getenv(const char *name);
  • name: 指定获取的环境变量名称。
  • 返回值: 如果存放该环境变量,则返回该环境变量的值对应字符串的指针;如果不存在该环境变量,则返回 NULL。

下面是一个使用 getenv() 函数获取这个环境变量的值的示例程序:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了环境变量名称作为命令行参数
    if (argc != 2) {
        printf("Usage: %s <environment-variable-name>\n", argv[0]);
        return 1;
    }

    // 获取环境变量的值
    const char *value = getenv(argv[1]);

    if (value != NULL) {
        printf("The value of '%s' is: %s\n", argv[1], value);
    } else {
        printf("The environment variable '%s' is not set.\n", argv[1]);
    }

    return 0;
}

通过程序查看SHELL环境变量的值,

4 添加/删除/修改环境变量

C 语言函数库中提供了用于修改、添加、删除环境变量的函数,譬如 putenv()、 setenv()、 unsetenv()、clearenv()函数等。

4.1 putenv()函数添加环境变量

putenv() 函数用于添加或修改环境变量的函数。它接收一个字符串参数,该字符串应该包含环境变量的名称和值,两者之间用等号(=)连接。如果环境变量已经存在,putenv() 会更新它的值;如果不存在,它将添加一个新的环境变量。其函数原型如下所示:

cpp 复制代码
#include <stdlib.h>

int putenv(char *string);
  • string: 参数 string 是一个字符串指针,指向 name=value 形式的字符串。
  • 返回值: 成功返回 0;失败将返回非 0 值,并设置 errno。

使用 putenv()函数为当前进程添加一个环境变量。

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
    if (2 > argc) {
        fprintf(stderr, "Error: 传入 name=value\n");
        exit(-1);
    }
    /* 添加/修改环境变量 */
    if (putenv(argv[1])) {
        perror("putenv error");
        exit(-1);
    }
    exit(0);
}

运行结果如下:

4.2 setenv()函数

setenv()函数可以替代 putenv()函数,用于向进程的环境变量列表中添加一个新的环境变量或修改现有环境变量对应的值,其函数原型如下所示:

cpp 复制代码
#include <stdlib.h>

int setenv(const char *name, const char *value, int overwrite);
  • name: 需要添加或修改的环境变量名称。
  • value: 环境变量的值。
  • overwrite: 若参数 name 标识的环境变量已经存在,在参数 overwrite 为 0 的情况下, setenv()函数将不改变现有环境变量的值,也就是说本次调用没有产生任何影响;如果参数 overwrite 的值为非 0,若参数 name标识的环境变量已经存在,则覆盖,不存在则表示添加新的环境变量。
  • 返回值: 成功返回 0;失败将返回-1,并设置 errno。

setenv()与 putenv()函数有两个区别:

  • putenv()函数并不会为 name=value 字符串分配内存;
  • setenv()可通过参数overwrite控制是否需要修改现有变量的值而仅以添加变量为目的,显然putenv()并不能进行控制。

setenv()函数使用示例程序如下:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了环境变量名称和值
    if (argc != 3) {
        printf("Usage: %s <variable-name> <value>\n", argv[0]);
        return 1;
    }

    // 使用 setenv 函数添加或修改环境变量
    // setenv 返回 0 表示成功,非 0 表示错误
    if (setenv(argv[1], argv[2], 1) != 0) {
        perror("Failed to set environment variable");
        return 1;
    }

    // 打印环境变量的值以验证
    const char *value = getenv(argv[1]);
    if (value != NULL) {
        printf("%s is now set to: %s\n", argv[1], value);
    } else {
        printf("Failed to retrieve the set environment variable.\n");
    }

    return 0;
}

程序首先检查是否提供了正确的参数数量。如接下来,程序使用 setenv() 函数来设置环境变量。setenv() 的第三个参数设置为 1,表示如果环境变量已经存在,允许覆盖它的值。然后,程序使用 getenv() 函数来验证环境变量是否已正确设置,并打印出它的值。运行结果如下:

4.3 unsetenv()函数

unsetenv() 是 POSIX 标准中定义的一个函数,用于从当前进程的环境中删除指定的环境变量。这个函数的原型通常如下:

cpp 复制代码
#include <stdlib.h>

int unsetenv(const char *name);
  • name :要删除的环境变量的名称。
  • 返回值:如果环境变量成功被删除,unsetenv() 会返回 0;如果发生错误,比如尝试删除不存在的变量,会返回非零值。

下面是一个使用 unsetenv() 函数的示例程序,它接受一个命令行参数(环境变量的名称),并尝试从当前进程的环境中删除这个变量:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char *argv[]) 
{
    // 检查是否提供了环境变量名称
    if (argc != 2) {
        printf("Usage: %s <environment-variable-name>\n", argv[0]);
        return 1;
    }

    // 尝试删除环境变量
    if (unsetenv(argv[1]) == -1) {
        perror("Failed to unset environment variable");
        return 1;
    }

    // 验证环境变量是否被删除
    const char *value = getenv(argv[1]);
    if (value == NULL) {
        printf("The environment variable '%s' has been unset.\n", argv[1]);
    } else {
        printf("The environment variable '%s' is still set to: %s\n", argv[1], value);
    }

    return 0;
}

运行结果如下:

相关推荐
憧憬一下12 小时前
驱动中的device和device_driver结构体
驱动开发·嵌入式
winddevil1 天前
[rCore学习笔记 029] 动态内存分配器实现-以buddy_system_allocator源码为例
rust·嵌入式·rcore
卑微求AC2 天前
(C语言贪吃蛇)14.用绝对值方式解决不合理的走位
linux·c语言·开发语言·嵌入式·c语言贪吃蛇
卑微求AC2 天前
(C语言贪吃蛇)13.实现贪吃蛇四方向的移动
linux·c语言·嵌入式·c语言贪吃蛇
玄奕子3 天前
GPT对话知识库——bootloader是什么?ymodel协议是什么?
stm32·gpt·嵌入式·传输协议·嵌入式驱动
FreakStudio3 天前
全网最适合入门的面向对象编程教程:55 Python字符串与序列化-字节序列类型和可变字节字符串
python·单片机·嵌入式·面向对象·电子diy
我想学LINUX4 天前
一文带你掌握 tmux -- 高效的终端复用工具
linux·嵌入式硬件·嵌入式·策略模式·tmux·tmux命令
极客小张4 天前
基于STM32和FPGA的射频数据采集系统设计流程
c语言·stm32·物联网·算法·fpga开发·毕业设计·嵌入式
winddevil5 天前
[rCore学习笔记 028] Rust 中的动态内存分配
rust·嵌入式·rcore
武汉唯众智创5 天前
嵌入式边缘计算软硬件开发“1+X”考证建设方案
嵌入式·边缘计算软硬件开发·嵌入式“1+x”