Linux相关概念和易错知识点(12)(命令行参数、环境变量、本地变量)

1.命令行参数

(1)main函数的参数int  argc和char*  argv[]是什么?

main函数可以带参数,即int  main(int  argc,  char*  argv[]),(int  argc,  char*  argv[])叫做命令行参数列表,int argc叫参数的个数,char* argv[]叫参数的列表。

当我们在Linux中输入./test执行程序时:argc == 1,argv[0] == "./test",当程序加载时我们写的一行字符串都会被根据空格拆分成多个小字符串,作为参数传进argv

下面就是个很好的例子

我特地在打印时使用了选项1、选项2来标识每个被拆分的字符串来作为引导。事实上,指令的本质就是C语言,这其实就是ls -a -l这种指令选项实现的原理。如test -opt1 -opt2 -opt3就会被转为4个字符串,分别对应argv的4个元素argv[0] ~ argv[3]。在main函数内显式调用argv[1]、argv[2]...,通过字符串比较对这些argv[num]字符串进行匹配,进而根据判断语句实现不同功能匹配。

在Linux指令中,命令行参数使得程序能有不同的功能和表现。但在我们自己平时写的代码中,很少用到这种功能,所以一般main函数不写参数。

(2)命令行参数是如何传递的?

ls -a -l...这一行被视为一个字符串,这个字符串首先被用户的父进程Shell(Linux中是-bash,CLI的具体实现程序)拿到,父进程将这个字符串按照空格分解为多个字符串,进而构建出了argc和argv(argv是动态分配空间的,根据拆分字符串数量决定开辟空间,argv末尾有结束标志,如argv[8] == NULL)。也就是说实际上最先拿到argc和argv这两个数据的是父进程-bash

当父进程创建子进程,也就是调用开始程序的时候,子进程会独立一份代码和数据,保持独立性,其中这部分数据里就有命令行参数列表argc和argv。也就是说bash启动程序形成的argc和argv列表其子进程也能看到。

这里需要注意的是,main并不是程序入口,main函数也是被其它函数调用的,在main函数前还有CRTstartup(),这个函数就会针对父进程传下来的数据调用main函数并决定是否传参数。main函数结束后的返回值也是交给CRTstartup()的。

2.环境变量

(1)main函数的第3个参数char*  env[]是什么?

main函数的参数其实还有一个char* env[](环境变量表的指针,实际上是char**  env)

这是另外一张表,每个元素都是一个环境变量,env[0]、env[1]......即可全部调用。最后一个元素之后同样有NULL标志。所有环境变量的格式都是key=value,如USER=SGlow,这看上去似乎是在展示某种属性,事实上环境变量是我们很多进程能运行起来的重要基础。很多指令和程序的执行都依赖环境变量里面的信息

使用env指令可以查看当前环境变量

(2)环境变量的全局属性

环境变量具有“全局”属性。具体地说,环境变量表继承自父进程,也可以继承给子进程。当我们用户登录Shell时,-bash进程被创建,此时它就拥有了一份环境变量表。不论这个用户以任何形式创建进程,归根到底这些进程都是bash的子进程,于是所有的进程用的环境变量表都是一样的。

我们可以在命令行使用env来对比test.c打印出来的环境变量表,发现是一样的。

因此我们称其为全局属性。至于环境变量出现的目的以及更多细节,我们后续会提到。

(3)借助PATH属性进一步了解环境变量

我们要思考一个问题:./test可以运行程序,但为什么test就不行呢?我们现在已经知道ls、pwd的本质也是C语言写的可执行程序,那为什么那些指令执行直接输入可执行程序名就可以了呢?

事实上,我们输入的每一条指令都会到/usr/bin等规定目录下去找,如果这些目录找不到就必须使用./test来指定调用程序了。像ls、pwd这些C语言程序就是如此,因为系统能找到这些程序,所以不用./ls或者./pwd

下面是/usr/bin目录下的一些指令对应的可执行程序

我们如果将我们写的可执行程序放到这个目录里,那就自然可以按指令的形式顺利运行了。

注意我们要先使用type (可执行程序名)看看是否和已有命令冲突,如果冲突了就要换名字。

但这不是唯一的方案,系统也不会只到这一个目录下查找。PATH环境变量就指定了系统以何种顺序进行查找

使用echo $PATH就可以查找当前环境变量的PATH。$是一个标志,后面跟的就是要查找的属性名

我们可以使用PATH=$PATH:$PWD来加上我们要执行的程序的目录。PWD也是环境变量的一种,它指向了我们当前的工作目录,指令pwd就是读取该环境变量。

需要注意的是PATH=(路径)会直接将右侧字符串替换回去,所以我们要保证格式规范,还有不要直接PATH=$PWD,这样默认路径就被覆盖了。这会导致一些指令无法运行(注意不是全部)

由于命令行是在-bash这个进程下进行的,所以每当我们cd时,环境变量的PWD就会修改,当有程序运行起来时,就会读取当前的PWD作为自己的cwd进程属性,这就是为什么bash的子进程都知道自己的cwd的原因。如果这些子进程再创建子进程,它们也会继承父进程的环境变量,知道自己的cwd。当然之前也说过,在代码中我们可以使用chdir("(路径)")来显式改变cwd,但我们要知道默认路径的根本是读取bash进程下的PWD。理解程序运行起来时进程属性cwd是如何确定的对我们深入理解环境变量有很大帮助。

(4)环境变量的配置

PATH=$PWD会覆盖默认路径,怎么抢救呢?事实上,我们只需要重新登陆系统即可解决。因为环境变量是内存级别的,我们指令修改PATH是修改的bash进程对应内存空间中的环境变量数据,而磁盘上的数据不会受到影响,所以退出重进就能完全恢复。

登录时,系统首先要创建bash进程来启动CLI,保证命令行的正常执行,所有用户登陆后都要干这件事。创建bash进程分为创建PCB和从磁盘中读取环境变量配置文件信息到内存两步,读取配置文件的本质是为了在内存中配置自己的配置文件,因为不同的用户初始时有不同的环境变量,像PWD、HOME、USER这些都需要按用户设置。

配置完环境变量后bash进程就基本创建完成了,各个环境变量都有值了,像HOME和PWD最开始都是指向自己的家目录(是因为HOME存的是这个值,所以那里才叫家目录)。同时bash也是一个进程,这个进程也有自己的cwd,它会使用类似chdir()的操作设置自己的cwd,这个cwd就是刚刚读取到的配置文件中HOME的路径,即家目录。

我们发现环境变量对于每个用户是独一无二的,是用户登录后需要尽快导入的数据,在bash进程的创建中也有很重要的作用。当我们理解清环境变量的内存级属性,以及它和bash之间的关系之后,我们对环境变量又有了一个新的认识,也对之前的进程的属性的认识更上一层楼。

但还有一些问题,这个配置文件在哪里?我们可以自己改吗?

这个配置文件在我们家目录下,当登录时会读取.bash_profile和.bashrc到内存中以修改形成当前用户的环境变量信息。因为.bash_profile和.bashrc在这个目录下,所以读取文件时的HOME就被默认设置为了该路径,因此配置的环境变量HOME就是该路径,导致家目录是该路径。家目录被设置在该目录的根本就是因为.bash_profile和.bashrc在这个目录下

在.bash_profile里面我们可以看到PATH的默认信息,这是存储在磁盘上的,每次登录都会被读取到内存上。我们可以加上自己的想要查询的路径,保存退出后,用source .bash_profile使配置文件生效,之后登录就能自动加到PATH环境变量

我们重新登录就会发现我们添加的默认信息已经生效了,当环境变量被配置时,我们的自定义路径就会在PATH中,我们之后就无需手动PATH=$PATH:(路径)

(5)一些环境变量的功能

在进程属性中我们能查到是谁启动的进程(uid),从而和文件的拥有组、所属组、other的uid匹配,进而控制权限。但是系统怎么知道谁启动的进程呢?就是USER=(用户名),当登录后导入环境变量,创建bash时系统就知道我们是谁了,不管创建多少进程,由进程数据的继承规则,系统永远知道我们用户的身份。

SHELL告诉我们登录时启动的Shell进程对应程序的路径,因为一个系统中可能有不同的Shell版本;LOGNAME和NAME一般来讲是一致的,是指当前的登录用户;OLDPWD是指上一条cd路径,它显然直接帮助cd - 这个指令实现

(6)环境变量的读取

env是整体查看,获取具体的信息可以使用管道 + grep筛选

getenv((环境变量key)),返回其value

unistd.h中有一个全局的变量char** environ(指向char* env[]数组),extern声明之后就可以使用

3.本地变量

(1)如何创建和使用

我们直接在命令行使用a=5,b=10就是在定义本地变量。我们可以借助while和for循环来进行一些批量化操作

其中说明(( 表达式 ))是算术表达式,其返回值用于条件判断,$(( 表达式 ))返回用于变量赋值。在(( 表达式 ))的表达式不需要写$(变量),能自动识别本地变量,运算结果也能自动修改变量。[[ 表达式 ]]和[ 表达式 ]还支持一些文本的比较,但都要写$。一般来说,我们略微了解即可。这种用法还催生出了Shell脚本.sh用来处理批量化任务(类似于Makefile),.sh本质也是一个文件,./之后也是按照Shell的逻辑一行一行执行。

(2)本地变量和本地变量表

用户登陆,创建bash进程时,除了环境变量表的导入,bash还创建了一个本地变量表,当我们在命令行使用a=10这种操作时a被直接加到本地变量表。

export a可以将本地变量mv到环境变量表中。export操作相当于直接将指针移动到环境变量表,移动到env中后本地变量表就没有这个变量了。

通过export,我们也可以使用export b=100直接添加到环境变量表中。unset (key)取消环境变量

(3)通过本地变量进一步了解环境变量

环境变量是可以被继承下去的,是一个全局有效的配置信息,每个子进程都能得到这个信息;而本地变量不能,它也不能被子进程看到。

在和本地变量的对比中,我们可以进一步看到环境变量的全局属性。系统的配置信息,尤其是指导性配置信息(当前用户是谁USER,工作路径PWD)都是交给环境变量来保管的,而不是本地变量。环境变量的导入是系统配置起效的一种表现,因为所有程序运行起来都是进程,而所有进程都遵循系统的配置信息,这就说明这个配置信息有了用处,否则配置信息就只能存在文件里,它并没有对系统造成实质性的规范和影响。

和本地变量相比,环境变量更倾向于在进程间传递只读数据,虽然我们可以进行内存级修改,但毕竟环境变量是程序启动的根基,所以一般都是以读的形式访问,这和本地变量有很大区别。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/440943.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RL_足球教练

文章目录 前言什么是 Agent?定义Agent的组成部分Agent的目标 什么是 End-to-End Approach?定义特点优势与挑战示例 Fuzzy Bayesian Reinforcement Learning (RB-RL)系统组成部分系统工作原理 贝叶斯方法基础_条件概率定义 贝叶斯定理示例敏感性 Q-learning强化学习算法Q-lear…

Pandas -----------------------基础知识(八)

Pandas内置Matplotlib 加载数据 import pandas as pdanscombe pd.read_csv(/root/pandas_code_ling/data/e_anscombe.csv) anscombe dataset_1 anscombe[anscombe[dataset]I] dataset_1dataset_1.describe() 提供数据 dataset_1 anscombe[anscombe[dataset]I] dataset_2 an…

【SQL】DDL语句

文章目录 1.SQL通用语法2.SQL的分类3.DDL3.1数据库操作3.2 表操作3.2.1 表操作--数据类型3.2.2 表操作--修改3.2.3 表操作--删除 SQL 全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库统一标准 。…

C++模板编程:深入理解分离编译的挑战与解决方案

文章目录 前言🍎一、非类型模板参数1.1 基本概念1.2 非类型模板参数的语法1.3 非类型模板参数的限制1.4 非类型模板参数的应用1.5 typename关键字 🍎二、类模板特化2.1 类模板特化的基本概念2.2 类模板特化的限制和规则2.3 类模板特化的应用 &#x1f34…

输电线路缺陷图像检测数据集,导线散股,塔材锈蚀两类,分别为581张和1407张,标注为xml和txt格式 1988张

输电线路缺陷图像检测数据集,分为导线散股,塔材锈蚀两类,分别为581张和1407张,标注为xml和txt格式 数据集名称 输电线路缺陷图像检测数据集 (Transmission Line Defect Detection Dataset) 数据集概述 该数据集是一个专门用于训…

查看 git log的过程中看到 :说明日志输出可能超出屏幕大小,系统进入了分页模式

在命令行提示符中,通常 : 表示系统等待进一步的输入。如果你在查看 git log 的过程中看到 :,说明日志输出可能超出屏幕大小,系统进入了分页模式,默认使用 less 命令查看内容。 此时你可以: 按 q 退出日志查看。按 En…

【图像处理】多幅不同焦距的同一个物体的平面图象,合成一幅具有立体效果的单幅图像原理(一)

合成一幅具有立体效果的单幅图像,通常是利用多个不同焦距的同一物体的平面图像,通过图像处理技术实现的。以下是该过程的基本原理: 1. 立体视觉原理 人眼的立体视觉是通过双眼观察物体的不同视角而获得的。两只眼睛的位置不同,使…

SSH -L 代理与反向代理转发详解

简介:SSH -L 选项用于设置本地端口转发,而反向代理转发则允许远程主机访问本地服务。本文将介绍如何使用 SSH -L 实现本地端口转发和反向代理转发,并提供示例以帮助您理解和应用这些技术。 历史攻略: Centos:设置代理…

百度文心智能体平台开发萌猫科研加油喵

百度文心智能体平台开发萌猫科研加油喵 在科研的道路上,研究生们常常面临着巨大的压力和挑战。为了给这个充满挑战的群体带来一些鼓励和温暖,我借助百度文心智能体平台开发了一个独特的智能体 《萌猫科研加油喵》。 一、百度文心智能体平台介绍 百度文…

设计模式之适配器模式(通俗易懂--代码辅助理解【Java版】)

文章目录 设计模式概述1、适配器模式2、适配器模式的使用场景3、优点4、缺点5、主要角色6、代码示例1)UML图2)源代码(1)定义一部手机,它有个typec口。(2)定义一个vga接口。(3&#x…

如何用python抓取豆瓣电影TOP250

1.如何获取网站信息? (1)调用requests库、bs4库 #检查库是否下载好的方法:打开终端界面(terminal)输入pip install bs4, 如果返回的信息里有Successfully installed bs4 说明安装成功(request…

操作系统 | 学习笔记 | 王道 | 3.1 内存管理概念

3 内存管理 3.1 内存管理概念 3.1.1 内存管理的基本原理和要求 内存可以存放数据,程序执行前需要先放到内存中才能被CPU处理—缓和cpu和磁盘之间的速度矛盾 内存管理的概念 虽然计算机技术飞速发展,内存容量也在不断扩大,但仍然不可能将所有…

Python面向对象基础

文章目录 1. 什么是面向对象1.1 常见的编程思想1.2 面向过程是什么1.3 什么是面向对象1.4 封装1.5 继承1.6 多态 2. 面向对象的概念2.1 两个重要概念:类和对象2.2 类2.3 对象2.4 self关键字 3. 对象属性3.1 什么是属性3.2 类外面访问属性3.3 类内部获取属性 1. 什么…

分治算法(4)_快速选择_库存管理III_面试题

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 分治算法(4)_快速选择_库存管理III_面试题 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论&#x1f…

esp8266 at指令链接wifi时一直connect disconnest

那是你的连接wifi的名字密码有误或者热点有问题,看看热点是不是把设备拉入黑名单或者设置为5G或者连了校园网或者设置了最多链接设备

sqli-labs靶场第三关less-3

sqli-labs靶场第三关less-3 1、确定注入点 http://192.168.128.3/sq/Less-3/?id1 http://192.168.128.3/sq/Less-3/?id2 有不同回显,判断可能存在注入, 2、判断注入类型 输入 http://192.168.128.3/sq/Less-3/?id1 and 11 http://192.168.128.3/sq/L…

【js逆向学习】极志愿 javascript+python+rpc

JSRPC使用方式 逆向目标逆向过程逆向分析1、什么是 websocket2、websocket的原理3、总体过程3.1 环境说明3.2 python服务端代码3.3 python客户端代码 4、Sekiro-RPC4.1 执行方式4.2 客户端环境4.3 参数说明4.4 SK API4.5 python代码调试4.6 代码注入流程 逆向总结 逆向目标 网…

大数据-155 Apache Druid 架构与原理详解 数据存储 索引服务 压缩机制

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

基于SpringBoot健身房管理系统【附源码】

效果如下: 系统首页界面 系统注册详细页面 健身课程详细页面 后台登录界面 管理员主页面 员工界面 健身教练界面 员工主页面 健身教练主页面 研究背景 随着生活水平的提高和健康意识的增强,现代人越来越注重健身。健身房作为一种专业的健身场所&#x…

28 基于51单片机的两路电压检测(ADC0808)

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,通过ADC0808获取两路电压,通过LCD1602显示 二、硬件资源 基于KEIL5编写C代码,PROTEUS8.15进行仿真,全部资源在页尾,提供…