当前位置: 首页 > news >正文

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指令可以查看当前环境变量,set输出所有环境配置、变量信息

(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)都是交给环境变量来保管的,而不是本地变量。环境变量的导入是系统配置起效的一种表现,因为所有程序运行起来都是进程,而所有进程都遵循系统的配置信息,这就说明这个配置信息有了用处,否则配置信息就只能存在文件里,它并没有对系统造成实质性的规范和影响。

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

相关文章:

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

1.命令行参数 (1)main函数的参数int argc和char* argv[]是什么? main函数可以带参数,即int main(int argc, char* argv[]),(int argc, char* argv[])叫做命令行参数列表,int argc叫参数的个数&a…...

wenserver中 一些常见的 错误码

EINTR 是 Linux 系统中定义的一个错误码,代表“被信号中断”。当一个系统调用在执行过程中被一个信号处理函数中断时,这个系统调用会立即返回错误,并且 errno 被设置为 EINTR。 举个例子 read函数是阻塞的 现在没有数据要读 我们read一直阻…...

【电路笔记】-求和运算放大器

求和运算放大器 文章目录 求和运算放大器1、概述2、反相求和放大器3、同相求和放大器4、减法放大器5、应用5.1 音频混合器5.2 数模转换器 (DAC)6、总结1、概述 在我们之前有关运算放大器的大部分文章中,仅将一个输入应用于反相或非反相运算放大器的输入。在本文中,将讨论一种…...

java实现桌面程序开机自启动

问题: 最近用java写一个桌面闹钟程序,需要实现开机自启动功能 解决办法: jna官网:https://github.com/java-native-access/jna?tabreadme-ov-file 使用jna库可以轻松实现 下载jna-5.15.0.jar和jna-platform-5.15.0.jar这两个库…...

Vuex 使用实例

文章目录 Vuex介绍使用步骤安装使用定义配置文件代码解释: 导入到 App.vue使用使用vuex Vuex 介绍 简单来说就是,多个组件需要共享一个data,原本只能通过父子组件来进行,但是vuex可以实现共享data 使用步骤 安装 npm install v…...

深度分离卷积

深度可分离卷积(Depthwise Separable Convolution)是一种高效的卷积操作,它将传统卷积操作分解为两个独立的步骤:深度卷积(Depthwise Convolution) 和 逐点卷积(Pointwise Convolution&#xff…...

JSONL 文件的检查和修订器

下面是一个JSONL 文件的检查和修订器,代码如下: import json import tkinter as tk from tkinter import filedialog, messageboxdef check_jsonl_file(input_file, log_file, output_file=None):errors = []valid_lines = []with open(input_file, r, encoding=utf-8) as in…...

输电线路悬垂线夹检测无人机航拍图像数据集,总共1600左右图片,悬垂线夹识别,标注为voc格式

输电线路悬垂线夹检测无人机航拍图像数据集,总共1600左右图片,悬垂线夹识别,标注为voc格式 输电线路悬垂线夹检测无人机航拍图像数据集介绍 数据集名称 输电线路悬垂线夹检测数据集 (Transmission Line Fittings Detection Dataset) 数据集…...

杭电合集小tips

刷HDU的题过程中&#xff0c;有一些值得注意的小问题&#xff0c;这里我踩坑之后记录下来&#xff0c;以便回顾与各位分享 一&#xff0c;关于语言的使用 主要大家还是用C和C多&#xff0c;但是注意的是&#xff0c;#include<bits/stdc.h>这个文件是G自带的&#xff0c…...

Python的输入输出函数

1.输入函数 Python的输入函数是input().input的引号里面是提示的内容&#xff0c;从键盘输入的任何字符都会当成字符串赋值给变量. n input("请输入:") print(type(n)) print(n) 输出结果为&#xff1a; 请输入:33 <class str> 33 2.输出函数 Python的内置…...

如何进行搭建与部署云主机?

云主机是一种基于虚拟化技术的服务器&#xff0c;云主机可以为用户提供一种非常高效且可扩展的计算机资源服务&#xff0c;主要是由操作系统和云硬盘等基础的计算组件所构成的&#xff0c;用户能够根据自身的需求来选择相关的配置规格&#xff0c;来满足不同的业务需求。 那么我…...

Biomamba求职| 国奖+4篇一作SCI

转眼间我也要参加秋招啦&#xff0c;认真的求职帖&#xff0c;各位老师/老板欢迎联系~其它需要求职的小伙伴也欢迎把简历发给我们&#xff0c;大家一起找工作。 一、基本信息 姓名&#xff1a;Biomamba 性别&#xff1a;男 出厂年份&#xff1a;1998 籍贯&#xff1a;浙江…...

Python 工具库每日推荐 【Pandas】

文章目录 引言Python数据处理库的重要性今日推荐:Pandas工具库主要功能:使用场景:安装与配置快速上手示例代码代码解释实际应用案例案例:销售数据分析案例分析高级特性数据合并和连接时间序列处理数据透视表扩展阅读与资源优缺点分析优点:缺点:总结【 已更新完 TypeScrip…...

电影选票选座系统|影院购票|电影院订票选座小程序|基于微信小程序的电影院购票系统设计与实现(源码+数据库+文档)

电影院订票选座小程序 目录 基于微信小程序的电影院购票系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、用户功能实现 2、管理员功能实现 &#xff08;1&#xff09;影院信息管理 &#xff08;2&#xff09;电影信息管理 &#xff08;3&#xff09;已完成…...

matlab初学习记录

文章目录 内置函数与变量matlab 编辑器数组等间距向量数组函数数组索引提取多个元素 对向量执行数组计算查看文档 画图添加注释 实践导入数据关系运算符分支恒星运动 matlab 学习看入门之旅 先计算等号右边再计算等号左边。 工作区记录等号右边的变量。 ; 表示的是抑制输出。…...

protobuf之Message

简介 Message是protobuf的消息抽象类&#xff0c;是其它通过protoc生成的自定义消息的基类 结构 #mermaid-svg-u5iAZNpfIH5hQrlP {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-u5iAZNpfIH5hQrlP .error-icon{fil…...

【redis-06】redis的stream流实现消息中间件

redis系列整体栏目 内容链接地址【一】redis基本数据类型和使用场景https://zhenghuisheng.blog.csdn.net/article/details/142406325【二】redis的持久化机制和原理https://zhenghuisheng.blog.csdn.net/article/details/142441756【三】redis缓存穿透、缓存击穿、缓存雪崩htt…...

二、MySQL的数据目录

文章目录 1. MySQL8的主要目录结构1.1 数据库文件的存放路径1.2 相关命令目录1.3 配置文件目录 2. 数据库和文件系统的关系2.1 查看默认数据库2.2 数据库在文件系统中的表示2.3 表在文件系统中的表示2.3.1 InnoDB存储引擎模式2.3.2 MyISAM存储引擎模式 2.4 小结 1. MySQL8的主要…...

2024.10月7~10日 进一步完善《电信资费管理系统》

一、新增的模块&#xff1a; 在原项目基础上&#xff0c;新增加了以下功能&#xff1a; 1、增加AspectJ 框架的AOP 异常记录和事务管理模块。 2、增加SpringMVC的拦截器&#xff0c;实现登录 控制页面访问权限。 3、增加 Logback日志框架&#xff0c;记录日志。 4、增加动态验…...

vue2项目的路由使用history模式,刷新会导致页面404的问题

在vue2项目中&#xff0c;如果我们使用的路由是history模式&#xff0c;刷新会导致页面404&#xff0c;解决方法很简单&#xff0c;在vue.config.js文件中的devServer下增加historyApiFallback: true; 代码如下: module.exports {devServer: {historyApiFallback: true,} }...

pytest框架之fixture测试夹具详解

前言 大家下午好呀&#xff0c;今天呢来和大家唠唠pytest中的fixtures夹具的详解&#xff0c;废话就不多说了咱们直接进入主题哈。 一、fixture的优势 ​ pytest框架的fixture测试夹具就相当于unittest框架的setup、teardown&#xff0c;但相对之下它的功能更加强大和灵活。 …...

【浏览器】如何正确使用Microsoft Edge

1、清理主页广告 如今的Microsoft Edge 浏览器 主页太乱了&#xff0c;各种广告推送&#xff0c;点右上角⚙️设置&#xff0c;把快速链接、网站导航、信息提要、背景等全部关闭。这样你就能得到一个超级清爽的主页。 网站导航       关闭 …...

打印1000年到2000年之间的闰年

我们要打印1000年到2000年之间的闰年&#xff0c;首先我们先输出1000年到2000年之间的所有的年份&#xff0c;同时我们将闰年的判断方法输入到其中 闰年需要满足下列两个条件的其中之一&#xff1a; 1.能被4整除但不能被100整除 2.能被400整除 打印1000年到2000年之间的闰年…...

nn.Identity()

在 PyTorch 中&#xff0c;nn.Identity()是一个简单的模块&#xff0c;它的作用是在模型中作为一个占位符或者不进行任何操作的层&#xff0c;直接返回输入。 一、使用方法 以下是一个简单的使用示例&#xff1a; import torch import torch.nn as nn# 创建一个 Identity 层…...

Java 快速排序

快速排序&#xff08;Quicksort&#xff09;是一种高效的排序算法&#xff0c;采用分治法&#xff08;Divide and Conquer&#xff09;的策略来把一个序列分为较小和较大的两个子序列&#xff0c;然后递归地排序两个子序列。以下是用Java实现的快速排序算法&#xff1a; publi…...

51单片机的智能衣柜【proteus仿真+程序+报告+原理图+演示视频】

1、主要功能 该系统由AT89C51/STC89C52单片机LCD1602显示模块光照传感器时钟模块温湿度传感器继电器按键、LED等模块构成。适用于智能衣柜、智能衣橱、紫外线定时消毒等相似项目。 可实现功能: 1、LCD1602实时显示北京时间、温湿度和开关门状态 2、时钟模块DS1302采集时间 …...

SAP_FI_表ACDOCA取代的表

在 SAP S/4HANA 系统中&#xff0c;ACDOCA&#xff08;通用分录表&#xff0c;Universal Journal&#xff09;引入了全新的数据结构&#xff0c;取代了原先 ERP 系统中多个财务和控制模块的表。ACDOCA 通过一个单一表格整合了财务会计&#xff08;FI&#xff09;和管理会计&…...

论文《OneLLM:One Framework to Align All Modalities with Language》

&#xff08;没有会员只有做100个节点&#xff0c;mindmaster金主爸爸可不可以给我一个会员啊啊啊啊呜呜呜~&#xff09; 欣赏论文的图和表&#xff1a; 表中作者将自己的模型那一行选择灰色作为背景&#xff0c;更加凸显自己的数据&#xff0c;另外对于最好的结果用加粗黑体…...

Ubuntu 22.04.4 LTS更换下载源

方法1&#xff1a;使用图形界面更换下载源 1. 打开软件和更新应用 2. 在Ubuntu 软件标签中&#xff0c;点击“下载自”旁边的下拉菜单&#xff0c;选择“其他” 3. 点击“选择最佳服务器”来自动选择最快的服务器 4. 选择服务器 5. 确定并关闭窗口&#xff0c;系统会提示您重新…...

html嵌入百度地图

html嵌入百度地图 key地址 https://lbsyun.baidu.com/apiconsole/key#/home &#xff0c;点进去注册应用、然后复制key换掉即可显示地图 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>百度地图搜索…...