命令行参数&&环境变量

目录

前言:

命令行参数:

现象:

这些参数的意义:

为什么要这么做?

这些事是谁做的呢?

环境变量

现象:

创建环境变量:

结合程序理解:


前言:

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

命令行参数:

现象:

我们是否还记得,我们在刚开始学习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内部有效,无法被子进程继承下去。只要导成环境变量,此时才能够被获取。

相关推荐
远游客07131 小时前
centos stream 8下载安装遇到的坑
linux·服务器·centos
马甲是掉不了一点的<.<1 小时前
本地电脑使用命令行上传文件至远程服务器
linux·scp·cmd·远程文件上传
jingyu飞鸟1 小时前
centos-stream9系统安装docker
linux·docker·centos
超爱吃士力架2 小时前
邀请逻辑
java·linux·后端
冷眼看人间恩怨2 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
cominglately4 小时前
centos单机部署seata
linux·运维·centos
魏 无羡4 小时前
linux CentOS系统上卸载docker
linux·kubernetes·centos
CircleMouse4 小时前
Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org
linux·运维·服务器·centos
木子Linux5 小时前
【Linux打怪升级记 | 问题01】安装Linux系统忘记设置时区怎么办?3个方法教你回到东八区
linux·运维·服务器·centos·云计算
mit6.8245 小时前
Ubuntu 系统下性能剖析工具: perf
linux·运维·ubuntu