文章目录
- [1. 命令行参数](#1. 命令行参数)
-
- [1.1 main函数的参数](#1.1 main函数的参数)
- [1.2 命令行参数的作用](#1.2 命令行参数的作用)
- [2. 环境变量](#2. 环境变量)
-
- [2.1 理解一个问题](#2.1 理解一个问题)
- [2.2 PATH环境变量](#2.2 PATH环境变量)
- [2.3 其他环境变量](#2.3 其他环境变量)
- [3. C/C++代码与进程之间的关系](#3. C/C++代码与进程之间的关系)
-
- [3.1 用代码获取环境变量](#3.1 用代码获取环境变量)
-
- [3.1.1 main函数最多有几个参数?](#3.1.1 main函数最多有几个参数?)
- [3.1.2 shell外壳里的环境变量是哪里来的?](#3.1.2 shell外壳里的环境变量是哪里来的?)
- [3.2 获取环境变量的若干种方法](#3.2 获取环境变量的若干种方法)
- [3.3 环境变量、本地变量、内建命令](#3.3 环境变量、本地变量、内建命令)
-
- [3.3.1 创建自己的环境变量](#3.3.1 创建自己的环境变量)
- [3.4 内建命令](#3.4 内建命令)

1. 命令行参数
1.1 main函数的参数
main函数是可以有参数的。main函数的参数由bash和系统自动传递。命令行参数的本质是一个字符串,shell以空格为分割符号,切成了若干的子串。
细节一:命令行参数至少是1,argc>=1,argv0一定会有元素,指向的就是程序名。
细节二:选项是以空格分割的字符串,一个字符也是字符串。
细节三:argv的本质是一张表,元素由argc决定,argvargc是最后一个,且始终为NULL。
1.2 命令行参数的作用
为什么要有命令行参数?命令行参数的本质应用,是为了实现一个命令可以根据不同的选项,实现不同的子功能。也是Linux中所有命令选项功能的实现方式。问题:VS2022有没有命令行参数?有的。cat file.txt 和 cat < file.txt 如何打印出文件内容?本质是通过命令行参数,将文件打开,打开后读文件,打印内容。
2. 环境变量
2.1 理解一个问题
环境变量具有全局属性的根本原因是:环境变量可以被bash进程的子进程继承,所有在Linux下的子进程都会拥有对应的环境变量。
./的本质是相对路径,本质是告诉OS,用户要执行的bin,就在当前路径下。
2.2 PATH环境变量
Linux怎么知道我应该去哪一个路径下找可执行程序?除了去 /usr/bin 路径下去找,还会不会去其他路径下去找?Linux系统,会存在所谓的环境变量的东西。
PATH是该环境变量的变量名:
bash
echo $PATH
以冒号为分割符的多串路径,告诉Linux系统,如果用户执行一个可执行文件,没有指明路径,去哪几个路径下去找?
PATH的本质是协助Linux进行指令查找的环境变量。
如何将路径配置到环境变量里?就可以执行的时候不带有 ./:
bash
PATH=[你的路径]
你这么写就直接覆盖了:
bash
PATH=$PATH:[你想要添加的路径]
总结:
PATH:指定命令的搜索路径。
PATH环境变量是全局的。
2.3 其他环境变量
系统级的变量,变量名和变量内容,往往具有全局属性。
还有没有其他环境变量?查询:
bash
env
介绍其余环境变量:
bash
echo $HISTSIZE
记忆你之前使用过的命令,默认是1000,统计最近使用的1000条命令。
bash
echo $OLDPWD
记忆用户在运行时上一次所存在的工作路径。
bash
echo $SSH_TTY
记录终端文件,终端窗口不一样,输入重定向对内容进行重新输入。
PATH :指定命令的搜索路径。当你在命令行输入一个命令时,系统会按照 PATH 中列出的目录顺序依次查找对应的可执行文件。
HOME :当前用户的主目录路径。执行 cd ~ 或 cd 不带参数时,就会跳转到该目录。不同用户的 HOME 不同,例如 /home/zhangsan 或 /root。
SHELL :当前用户所使用的 Shell 解释器的路径。常见的有 /bin/bash、/bin/zsh 等,决定了你在终端中使用的命令解释器类型。
3. C/C++代码与进程之间的关系
3.1 用代码获取环境变量
3.1.1 main函数最多有几个参数?
三个参数,拿到系统的环境变量表,本质是将环境变量表传递给进程。
有什么用?不同的环境变量有不同的用途。
是谁传递的?怎么传递的?
环境变量在bash没有拿到的时候在哪里?
是谁传递给你的?默认是在bash内部的,bash本质是一个进程,是存储在内存中的,是临时表,内存级的。我的程序都是bash进程的子进程,子进程代码和数据是可以共享的,是父进程传递的。
所以环境变量具有全局属性。
存在两张环境变量表,当我们运行程序时,bash会fork出一个子进程,子进程可以看到父进程的参数。所以说,不传参数也能看到环境变量的原因是,子进程进行了继承。
不传参数怎么获取环境变量?
子进程都是bash的子进程,你可以获得bash的表,子进程天然可以继承父进程的数据。
语言会默认提供全局变量,全局的指针可以指向环境变量表。获取环境变量的第二种方式。
需要记住的是,环境变量可以被获取。
bash有两张表,一张是命令行参数表,一张是环境变量表。
3.1.2 shell外壳里的环境变量是哪里来的?
bash的环境变量是哪里来的?是从Linux系统的配置文件里面来的,启动时会把配置文件加载进来,所以当时你改的是内存级的数据,你关掉Xshell又打开会重新从配置文件中加载。
什么是配置文件,配置文件又是哪里来的?
家目录存在两个配置文件:
.bashrc
.bash_profile
上面的两个文件其实是相关的。
bash在启动时,会访问
.bashrc文件,会将配置文件载入,修改一下就可以看到bash被执行,echo一行字就可以了。
root怎么不执行?每一个人都会有自己的家目录,改的不是root的配置文件。
为什么会给每个用户都搞一个bash?
bash
while :; do ps axj | grep bash ; sleep 1; done
while :; do ps axj | grep bash ; sleep 1; echo "#############"; done
每开一个窗口就会有一个bash,每个子进程都会加载一个环境变量。
最常见:
bash
man getenv
原理是,根据名字查找环境变量的内容,根据环境变量名遍历这张表,并依次比较,遍历成功将右边返回,失败返回NULL。
如何用C/C++获取环境变量:
C
char *whoami = getenv("USER");
3.2 获取环境变量的若干种方法
环境变量的作用是限制程序的执行。
获取环境变量的三种做法:
- main函数参数:
char* env[] - C语言全局变量:
char** environ - 最佳实践:
getenv(name)
测试:限制访问用户名。
3.3 环境变量、本地变量、内建命令
3.3.1 创建自己的环境变量
我想创建一个自己的环境变量怎么办?
bash
test_env=12344
env | grep TEST_ENV
存在但env不到,这个叫本地变量。
导出成环境变量:本质是在将本地变量放到环境变量表里,你就可以查到了:
bash
export TEST_ENV
再次查询就有了。
如果这个本地变量本来就没有,可以用export直接导也可以:
bash
export AAA=asdfghj
能不能被自己的C语言程序获得?
C
getenv("TEST_ENV");
子进程是可以获得父进程环境变量的,环境变量是全局的本质:环境变量是可以被子进程继承的。
如何删除环境变量:
bash
unset [环境变量名]
取消命令行的环境变量:本质就是将环境变量,从环境变量表中删除。
其实,这些也都是内存级的,关掉重新打开就好了。
本地变量和环境变量的区别:本地变量无法被子进程继承,不具备全局性,只在bash内部可以访问!!
类比于局部变量和全局变量。
为什么要有本地变量?
bash
cnt=0; while [ $cnt -le 100 ]; do echo $cnt; let cnt++; done
shell当中的本地变量是为了支持语法的,用于保存一些临时信息。
bash
set
可以查询系统变量和环境变量。
如果我想让我的环境变量关掉打开后还有,打开 .bash_profile,在里面export导入一个环境变量。
3.4 内建命令
提出问题:
本地变量只能在shell内部运行,不能被子进程继承。
echo子进程看不到本地变量是如何被打印的?
- echo这个进程是怎样能打印本地变量的?
命令和命令是不一样的,存在二进制文件级别的命令:
普通命令:
内建命令:在shell内部自己定义,bash自己内部的一次函数调用,不依赖第三方路径。
内建命令是shell自己的,意味着内建命令的执行不需要环境变量。
欢迎大家批评指正!!!