【Linux】九.进程概念--环境变量及其相关指令

发布时间:2026/7/5 15:26:59
【Linux】九.进程概念--环境变量及其相关指令 一.基本概念一般我们在安装Java/Python这些编程软件的时候就总是会说要在操作系统安装对应的环境变量在windows任务管理器中如下图就是我作为用户系统显示的环境变量。1-1 基本概念• 环境变量(environment variables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数• 如我们在编写C/C代码的时候在链接的时候从来不知道我们的所链接的动态静态库在哪⾥但是照样可以链接成功⽣成可执⾏程序原因就是有相关环境变量帮助编译器进⾏查找。• 环境变量通常具有某些特殊⽤途还有在系统当中通常具有全局特性.1-2 常⻅环境变量PATH:指定命令的搜索路径HOME :指定⽤⼾的主⼯作⽬录(即⽤⼾登陆到Linux系统中时,默认的⽬录)SHELL理解起来就是当前shell,它的值通常是/bin/bash。HISTSIZE命令历史记录保存数量。Ubuntu 22.04 默认是 3000 条命令history可以查看所有命令历史记录。搭配管道 history | wc -l 可以查看命令历史记录的行数。1-3 查看环境变量⽅法env:查看所有环境变量echo $PATH 查看环境变量PATH 是环境变量的名称查看指定环境变量。1-3-1环境变量PATH问题我们编写的c/c代码形成的可执行程序是不是一个指令呢答案是的在 Linux 中任何一个可执行程序具有可执行权限也称为它是一条命令。类比之前我们听到的命令指令程序可执行程序本身就是一个概念。那问题来了为什么我们执行ls这个指令不需要用./这些符号而运行我之前的test.c文件的时候要运行答案就是环境变量 PATH 中保存的是指定命令的搜索路径。因为 ls 等命令是在系统的特定路径下保存起来的而 test 命令没有保存在 PATH 指定的这些路径中因为系统执行命令又只会在 PATH 指定的这些路径中搜索那么系统就找不到我们的 test 命令所以就报错了,就显示上图的反应。那有没有办法不用添加./就能让程序跑起来法 1把 test拷贝到环境变量 PATH 指定的任一路径下。法 2把 test所在路径添加到环境变量 PATH 中。自己添加的环境变量系统重启后是不会被保存的,下次运行需要手动自己进行输入$ PATH$PATH:/home/ubuntu/xxx/10 # :冒号是分隔符 # 注意PATH/home/ubuntu/xxx/10不能这样写必须加上$符号否则会把PATH中所有内容覆盖掉这里不能直接用test是因为操作系统内bash的内置命令系统会优先调用内置的test,所以我把test改为mytest方便运行同时不用./就可以单独运行同时也可以不用改名字chmod x testenable -n testtest提示此方法为临时禁用系统内置命令不推荐长期使用优先建议重命名程序。注意如果我们不幸把环境变量给覆盖掉了不害怕。环境变量既然是变量说明它是可以被赋值的即在用户登录时通过用户目录下的配置文件赋值的所以只需要重新登录就好了。比如在家目录下的 .bash_profile 文件这些文件不要自己去随意修改1-3-2环境变量HOME⽤root和普通⽤⼾分别执⾏echo $HOME,对⽐差异执⾏ cd ~; pwd ,对应 ~ 和 HOME 的关系cd ~的意思是切换到当前用户的主目录home directory。不同用户的家目录中的配置文件不一样所以不同用户下的环境变量 HOME 也是不一样的。【补充】和环境变量相关的命令env:查看所有环境变量unset:清除环境变量set:显⽰本地定义的shell变量和环境变量echo显示某个环境变量值。二.获取环境变量C库函数getenv1getenv/setenv介绍name环境变量的名称。返回值环境变量的内容。分别举例说明#includestdio.h #include stdlib.h char *getenv(const char *name); // 获取环境变量 int setenv(const char *name, const char *value, int overwrite); // 更改或添加环境变量#include stdio.h #include stdlib.h // getenv int main() { printf(%s\n, getenv(PATH)); printf(%s\n, getenv(HOME)); printf(%s\n, getenv(SHELL)); return 0; }绝大多数进程为父进程bash 创建子进程然后由子进程执行用户输入的命令。三.环境变量和本地变量3-1.环境变量在命令行中我们通常可以定义两种变量环境变量环境变量通常具有全局属性可以被子进程继承下去环境变量实际上是在当前 bash 的上下文中定义的。所以在当前命令行解释器 bash 内可以被访问到在当前bash 创建的子进程下内也可以被访问到。#include stdio.h #include stdlib.h int main() { char* env getenv(MYENV); if(env) { printf(%s\n, env); } return 0; }运行结果直接运行发现没有结果说明该环境变量根本不存在。导出环境变量export MYENVhello world再次运行程序发现有结果表明环境变量是可以被子进程继承下去的。export 告诉bash这个变量要导出到环境里让后续的子进程比如你运行的程序能看到它。MYENVhello world 定义变量名和值注意等号两边不能有空格。3-2.本地变量本地变量只能在当前 shell 命令行解释器内被访问不可以被子进程继承如何查看本地变量呢echo $MY_val(当前我输入的本地变量如何证明本地变量不能被子进程继承// test.c #include stdio.h #include stdlib.h // getenv int main() { printf(%s\n, getenv(MY_VAL)); return 0; }运行结果当我们输入 ./test 后bash 会创建子进程来执行 test 程序。但因为本地变量 MY_VAL 只能在当前 bash 内被访问不能被其子进程继承所以子进程中的 getenv(MY_VAL) 函数获取不到本地变量 MY_VAL导致程序报错。bash父进程你输入命令的终端窗口对应的shell进程。子进程bash执行 ./test 时创建的、运行 test 程序的进程。解决方法可以将本地变量 MY_VAL 设置成环境变量。exprot MY_VALMY_VALHello world运行结果问题上面说到运行的大部分命令都是 bash 创建子进程来执行的而本地变量不能被子进程继承那为什么使用 echo 命令可以访问本地变量呢四.命令行参数4-1main 函数的参数列表main 函数可以带参但大部分都是缺省。argc命令行参数的个数。argv字符指针数组指向各个命令行参数的字符指针所构成的数组。运行结果只有一个元素时的当可以输入许多指令参数的时候的结果实际上我们输入的命令行参数就是一个个的 C 字符串./test、a、b、c传给了 main 函数.4-2命令行参数的意义帮助我们能够给同一个程序设计出不同的业务功能。#include stdio.h #include string.h int main(int argc, char *argv[]) { int show_all 0; // -a int show_long 0; // -l // 解析命令行参数 for (int i 1; i argc; i) { if (strcmp(argv[i], -a) 0) show_all 1; else if (strcmp(argv[i], -l) 0) show_long 1; else printf(未知参数: %s\n, argv[i]); } // 模拟功能输出 printf(选项解析结果:\n); printf(show_all (-a) %d\n, show_all); printf(show_long (-l) %d\n, show_long); return 0; }运行结果总结命令行参数可以让同一个命令通过带上不同的选项表现出不同的功能和作用。比如ls -l -a、ls -al。这就是命令行参数的意义。程序一般从main函数进入那main函数是谁在调用在 VSWindows中启动函数是mainCRTStartup它负责初始化运行时、获取命令行参数和环境变量然后调用你的main(argc, argv, envp)main 返回后它再调用exit()做清理并终止进程五.环境变量的组织方式每个程序都会收到⼀张环境表环境表是⼀个字符指针数组每个指针指向⼀个以’\0’结尾的环境字符串main 函数除了可以传递两个和命令行参数相关的参数 argc 和 argv 以外还传递第 3 个参数 envint main(int argc, char *argv[], char *env[])5-1通过代码如何获取环境变量命令⾏第三个参数// test.c #include stdio.h #include string.h int main(int argc, char* argv[], char* env[]) // 通过第三个参数接收环境变量 { for (int i 0; env[i]; i) //进行遍历遍历到NULL停止 { printf(env[%d]: %s\n, i, env[i]); // 遍历字符指针数组env } return 0; }运行结果获取到了当前 bash 内的所有环境变量。因为环境变量被 bash 创建的子进程 proc 继承下去了所以 C 库函数 getenv 的实现原理了输入printf(%s\n,getenv(PATH));其实就是通过在字符指针数组 env 中进行字符匹配找到 PATH 后面的内容并返回。5-2通过第三⽅变量environ获取C/C 提供了一个全局二级指针变量 char** environ指向存放环境变量地址的字符指针数组 char* env[ ]#include stdio.h int main(int argc, char *argv[]) { extern char **environ; int i 0; for(; environ[i]; i){ printf(%s\n, environ[i]); } return 0; }libc中定义的全局变量environ指向环境变量表,environ没有包含在任何头⽂件中,所以在使⽤时 要⽤extern声明。