命令行参数&&环境变量

目录

前言:

命令行参数:

现象:

这些参数的意义:

为什么要这么做?

这些事是谁做的呢?

环境变量

现象:

创建环境变量:

结合程序理解:


前言:

我们在前一章就开始学习与进程相关的部分知识,上一章是先学习到了进程优先级接下来就是补充一些额外知识。

命令行参数:

现象:

我们是否还记得,我们在刚开始学习C语言的时候,对于main函数的写法我是介绍过的,我记得我说过main函数可以写成这样:int main(int argc, char* argv[]) 。我们当然是可以选择这样写也可以直接选择int main()这样直接完事。下面我们来看下列的代码:

输出结果:

当然我们还可以再尝试一下:

输入指令:./test -a -b -c -d

这些参数的意义:

我们在通过点斜杠运行可执行程序后,通过添加-a或者-b这样的参数即可看到argc和argv的变化,其实这些是和该进程匹配的选项,这些选项以这些空格作为分隔符,把他们放进一个指针数组里。

其实作为区分的本质是将空格转换成'\0'加以区分的!

为什么要这么做?

可以通过输入不一样的选项,执行同一份代码的不同功能。以下通过代码举例子:

命令行参数本质是交给我们程序不同的选项,用来定制不同的程序功能。命令中会携带很多选项。

这些事是谁做的呢?

主要还是由我们的父进程bash(命令行解释器)管理,所以我们就可以得出以下结论:父进程的数据,默认能够被子进程看到并访问。命令行中启动的进程,都会变成进程,其实都是bash的子进程。

所以对我们之前通过点斜杠 运行的可执行程序,默认是输入给父进程bash的。

因为子进程能看到父进程的数据,因此bash在识别几个-a -b -c后传递到argc,并再malloc出argv[],这些都是子进程能看到的。现在我们也能理解,为什么有些指令类似ls后面还会有一个-l或者-a这样的选项的意思了。

环境变量

环境变量(environment variables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是有相关环境变量帮助编译器进行查找。

环境变量通常具有某些特殊用途,还有在系统当中通常具有全局特性。相信大家如果配置过java或者嵌入式stm环境得物时候为这个环境变量抓狂过,接下来我们就来了解下环境变量!

现象:

在Linxu中,存在一些全局的设置,表明告诉bash(命令行解释器),应该在哪些路径下去寻找可执行程序。

我们可以尝试输入指令:echo $PATH

系统中有很多配置,在我们登录Linux系统的时候,就已经被加载到了bash进程中(在内存中的),默认查找到的环境变量是内存级的。

PATH其实环境变量的一种,而我们$PATH无非就是将环境变量的内容存放地打印出来,我们将结果打印出来的内容:PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/ws/.local/bin:/home/ws/bin

这一串就是表示了各个环境变量存放的位置,比如/usr/local/bin这个文件夹,里面的可执行程序在该文件夹中,就代表了环境变量。其中 ":" 表示分隔符,bash在执行命令的时候,需要先找到命令,因为未来要加载。

刚刚我们讲命令行参数时,其实就有疑问了,运行test可执行程序时是要加点斜杠 的,再加上-a -b之类的选项,然后我说这可以说明ls为什么有-l -a选项对应不同的功能。此时我们就会发现,ls这个指令就不用加点斜杠 运行, 这又是为什么呢?

其实这个就是讲解环境变量最好的例子,这是因为bash会先去各个地址找,然后发现了ls在/usr/bin目录中

然后就会调用ls,所以在执行ls时就不用加点斜杠

创建环境变量:

若是,我想要自己的可执行程序和系统指令一样,不带点斜杠该怎么办呢?目前我们介绍三种方法。

1、可以尝试使用cp命令,将自己的可执行程序拷贝到/usr/bin目录下。

首先我需要给我的test可执行程序改名字,因为/usr/bin目录下有test这个环境变量。目前我们单独使用my_test是不起作用的,which也没有结果。所以我们开始进行拷贝。

演示成功啊,运行成功,和上面演示的一样。

2、也可以直接PATH =$PATH:"自己当前的目录",对于我的目录我就可以写成:

当然这种方式慎用,但是也没关系。因为我们每一次重启,环境变量右会重新归为。这是因为最开始的环境变量并不是在内存中的,而是在系统的对应配置文件中(默认在配置文件中)。

这个配置文件就在用户家目录下,.bash_profile文件、.bashrc文件和/etc/bashrc文件。其中前两个是用户的配置文件,最后一个是系统的配置文件。

所以如果我们想要永久更改环境变量的路径,可以直接在.bash_profile里更改。

见见更多的环境变量

可以输入:env 查看全部的环境变量。

这些环境变量都是极其准备好的。

export "环境变量名" = "环境变量内容" ------ 添加

unset "环境变量" ------ 取消

结合程序理解:

环境变量默认是可以被子进程拿到的!因为环境变量们,默认实是在bash里的。

而这些环境变量均是全局的!

环境变量有那么多,bash内部是如何组织的呢?

其本质是有一串代码组织的,extern char** environ;

接下来通过代码演示一下

不难发现,通过代码发现和我们直接输入env这个指令没有区别的。

bash再进程启动的时候,默认会给我子进程形成两张表:

argv[ ]命令行参数表(从用户输入命令行获取),env[ ]环境变量表(从OS的配置文件获取),bash通过各种方式交给子进程。

所以我们对于命令export XXX = XXX就是去env[ ]表里寻找NULL的地方,然后链入新的环境变量即可。

环境变量具有系统级的全局属性,因为环境变量本身会被子进程继承下去

以下是获取环境变量的三种方法:

  1. char* path = getenv("PATH")
  2. 通过main函数参数char* env[ ]
  3. extern char** environ

在执行export添加新环境变量时不会创建子进程吗?

子进程自己的数据bash看不到,但是export新的环境变量bash是可以看到的。当然执行export不会创建子进程,echo也不会创建子进程。这是因为export和echo是属于内建命令,这些命令是会有bash亲自执行。但是这只是一部分,因为80%的命令都是由bash创建子进程,子进程来执行的。

对于内建命令,可以理解为bash内部的一个个void类型的函数,执行完就执行完,并没有返回值。

注意!!!

如果你只是在输入指令:HELLO = 1234 这样子输入,你本质只是创建了一个本地变量 ,而不是环境变量!你可以使用echo $HELLO打印出来

但是你无法通过env|grep HELLO 查找出来,通过main函数或者extern char** environ这两种方法也查找不到!

本地变量只在ash内部有效,无法被子进程继承下去。只要导成环境变量,此时才能够被获取。

相关推荐
·云扬·6 小时前
从零开始搭 Linux 环境:VMware 下 CentOS 7 的安装与配置全流程(附图解)
linux·运维·centos
ReedFoley7 小时前
【笔记】动手学Ollama 第七章 应用案例1 搭建本地AI Copilot编程助手
人工智能·笔记·copilot
长安即是故里8 小时前
Maxwell学习笔记
笔记·学习
btyzadt10 小时前
虚拟机蓝屏问题排查与解决
linux·运维·网络
咸甜适中10 小时前
rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(十四)垂直滚动条
笔记·学习·rust·egui
小李独爱秋10 小时前
UNIX发展历史与核心技术解析
服务器·操作系统·unix
努力敲代码的小盆友11 小时前
[自用笔记]上传本地项目至github
笔记·github
G_H_S_3_11 小时前
【网络运维】Shell 脚本编程:while 循环与 until 循环
linux·运维·网络·shell
coderklaus11 小时前
Shell 基础知识
linux·macos·shell
争不过朝夕,又念着往昔12 小时前
即时通讯项目---网关服务
linux·c++·vscode