嵌入式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;
}

运行结果如下:

相关推荐
jjyangyou21 小时前
物联网核心安全系列——物联网安全需求
物联网·算法·安全·嵌入式·产品经理·硬件·产品设计
憧憬一下2 天前
Pinctrl子系统中Pincontroller和client驱动程序的编写
arm开发·嵌入式·c/c++·linux驱动开发
蓝天居士2 天前
ES8388 —— 带耳机放大器的低功耗立体声音频编解码器(4)
嵌入式·音频·es8388
田三番2 天前
使用 vscode 简单配置 ESP32 连接 Wi-Fi 每日定时发送 HTTP 和 HTTPS 请求
单片机·物联网·http·https·嵌入式·esp32·sntp
启明智显2 天前
AI笔筒操作说明及应用场景
人工智能·嵌入式硬件·嵌入式·ai大模型·启明智显·esp32-s3
FreakStudio2 天前
全网最适合入门的面向对象编程教程:58 Python字符串与序列化-序列化Web对象的定义与实现
python·单片机·嵌入式·面向对象·电子diy
Projectsauron6 天前
【STM32】通过 DWT 实现毫秒级延时
stm32·嵌入式·dwt
云中双月6 天前
如何使用Ida Pro和Core Dump文件定位崩溃位置(Linux下无调试符号的进程专享)
linux·嵌入式·gdb·调试·gcc·崩溃·ida pro·ulimit·core dump·cross compile
L_Z_J_I8 天前
超子物联网HAL库笔记:准备篇
笔记·物联网·嵌入式
飞凌嵌入式8 天前
FET113i-S核心板已支持RISC-V,打造国产化降本的更优解 -飞凌嵌入式
嵌入式硬件·嵌入式·risc-v·飞凌嵌入式