【Linux内核揭秘】深入理解命令行参数和环境变量

在这里插入图片描述

文章目录

  • 命令行参数
    • 什么是命令行参数
    • main函数的参数
  • 环境变量
    • 什么是环境变量
    • 常见的环境变量
      • PATH
      • HOME
      • SHELL
      • PWD
      • OLDPWD
  • 本地变量
  • 总结

命令行参数

什么是命令行参数

在这里插入图片描述

形如这样的命令后面带的选项就是命令行参数。
首先我们要了解一下命令行参数的原理。
我们知道像ls,mkdir,touch等等这些命令,都是用C语言写的可执行程序,所以必定会有main函数,我们以前学习C语言的时候也接触过一种main函数内部是传递参数的,学习C语言的时候,很难理解这些参数是什么意思,是因为这些参数是系统层面的,而不是语法层面的。
我们要理解命令行参数就需要先解决main函数的参数的问题。

main函数的参数

 int main(int argc,char *argv[])

上面这两个就是main函数的参数了,我们来尝试打印main函数的参数,因为argv对应的是字符串数组,所以我们尝试来打印一下这个数组。

#include<stdio.h>
int main(int argc,char *argv[])
{int i=0;printf("argc=%d\n",argc);for(i=0;i<argc;i++){printf("argv[%d]=%s\n",i,argv[i]);}return 0;
}

在这里插入图片描述
可以看见数组当中只有一个元素,假设我们带点选项:
在这里插入图片描述
这里我们空格隔开的字符串一共有4个对应的数组元素也是四个,那么这样有什么用呢?
这里展示一个样例,就可以知道这个命令行参数有什么用了。
用下面的代码来简单模拟一下命令行参数的机制:

#include<stdio.h>
#include<string.h>
int main(int argc,char *argv[])
{if(argc!=2){printf("Usage:code opt\n");}if(strcmp(argv[1],"-opt1")==0){printf("功能1\n");} if(strcmp(argv[1],"-opt2")==0){printf("功能2\n");} if(strcmp(argv[1],"-opt3")==0){printf("功能3\n");}return 0;
}

可以看见运行结果:
在这里插入图片描述
每个选项都可以实现一种功能。

命令行参数存在的意义:同一个程序可以根据命令行参数,根据选项的不同,表示出不同的功能。
但是问题又来了,main函数是程序执行的入口,但是main函数的参数是谁传进来的呢?
在这里插入图片描述
首先我们输入上面这个命令的时候,根据上面所知道的,这其实是一个字符串,然后这些字符串首先会被shell拿到,被shell拿到之后,会根据空格打散形成一张表argv和元素个数argc
由于命令行启动的程序的父进程都是shell,所以命令行启动的命令都是shell的子进程,子进程的PCB还有大多数属性都是继承的父进程的,所以子进程也看得到这个表,所以main函数的参数就被这样传进来了。

在这里插入图片描述
这个表的结尾是NULL。

环境变量

什么是环境变量

其实上面讲到的main函数的参数并不全,要说全的话,main函数的参数还有一个env,也是一个char*的数组:
main函数:

 int main(int argc,char *argv[],char *env[])

这才是main函数参数的全部,首先我们找到这张表的结尾是NULL,我们来打印这张表看看,第三个参数就是环境变量。
打印环境参数表:

#include<stdio.h>
int main(int argc,char *argv[],char *env[])
{int i=0;for(i=0;env[i]!=NULL;i++){printf("env[%d]:%s\n",i,env[i]);}
}

在这里插入图片描述

XDG_SESSION_ID=2654
HOSTNAME=hcss-ecs-e091
TERM=xterm
SHELL=/bin/bash
HISTSIZE=10000
SSH_CLIENT=125.66.243.232 45509 22
SSH_TTY=/dev/pts/0
USER=newuser
LD_LIBRARY_PATH=:/home/newuser/.VimForCpp/vim/bundle/YCM.so/el7.x86_64
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=01;05;37;41:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=01;36:*.au=01;36:*.flac=01;36:*.mid=01;36:*.midi=01;36:*.mka=01;36:*.mp3=01;36:*.mpc=01;36:*.ogg=01;36:*.ra=01;36:*.wav=01;36:*.axa=01;36:*.oga=01;36:*.spx=01;36:*.xspf=01;36:
MAIL=/var/spool/mail/newuser
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/newuser/.local/bin:/home/newuser/bin
PWD=/home/newuser/lesson12
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/home/newuser
LOGNAME=newuser
SSH_CONNECTION=125.66.243.232 45509 192.168.6.60 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/1000
HISTTIMEFORMAT=%F %T newuser 
_=./proc
OLDPWD=/home/newuser

可以看见系统中有很多环境变量,我们不打印env会更清晰:
这里展示部分:
在这里插入图片描述
所有环境变量都是通过key对应value来表示的=左边是key,=右边是value,这种kv方式构建的具有全局属性的变量叫做全局变量。
在这里插入图片描述
env这张表会一一对应的指向对应的环境变量。
说了这么多,那什么是环境变量?—在 Linux 中,环境变量是用于在操作系统和程序之间传递配置信息的一种机制。环境变量以键值对的形式存在,并在系统或用户会话中定义,用于存储与系统配置、应用程序执行以及用户偏好相关的信息。

常见的环境变量

PATH

PATH:
为什么我们能直接运行系统写好的命令,也就是程序,为什么我们运行我们的程序的时候需要在前面加上./
首先我们先来查看一下PATH这个环境变量,查看环境变量的第一种方法是在代码中遍历整个环境变量表,第二种就是利用echo来查看,但是不能echo PATH因为这样系统会将其识别为一个字符串,需要在PATH前面加上一个$符号,系统才会将其识别为一个变量。
在这里插入图片描述
PATH下是一系列路径,不同路径之间用:隔开。
现在回到刚刚的问题,为什么系统知道自己的程序在哪,但是不知道我们的程序在哪?因为shell在登录的时候,有一个环境变量PATH告诉shell你应该到哪里去找,所以系统知道自己的程序在哪里,那我们是否可以像系统这样不加./呢,答案是可以的。
方法1:将我们的可执行程序拷贝到usr/bin目录下
方法2:给环境变量PATH添加一个新的路径

我们说说方法2:
首先不可以这样:

PATH=可执行文件所在路径

这样做直接将原本系统的PATH给直接覆盖了,所以我们应该在以前的PATH下追加上当前路径。
像这样:

PATH=$PATH:可执行程序所在路径

在这里插入图片描述
可以看到环境变量就加好了,但是我们会发现,当我们退出系统时,还是运行不了自己的文件,原因是因为,每次在登录时,shell都要根据配置文件来更新PATH,我们只是在内存临时写入了环境变量,重新启动系统时,配置文件还是没变,所以要我们重新启动时还是能运行自己的程序,需要在配置文件中添加上我们的对应路径。
在这里插入图片描述
这两个文件就是我们对应的PATH的配置文件,这个目录是在home当中,这些都是隐藏文件,需要用ls -al才能查看到。
我们进入到第一个文件当中:
在这里插入图片描述
将红框上面的那句注释掉改成下面注释掉的就好了,其实就是在原本的路径上加上了我们自己相加的路径而已。
像这样配置文件就改好了。

HOME

在这里插入图片描述
HOME 环境变量在 Linux 系统中用于指定当前用户的主目录路径。它的值通常是 /home/username,其中 username 是登录用户的用户名。例如,如果用户的用户名是 alice,那么 HOME 的值通常是 /home/alice

不同用户对应的HOME变量是不同的,刚登录上系统时,当前目录就是家目录HOME。

SHELL

SHELL 环境变量在 Linux 系统中表示当前用户默认使用的命令行解释器(Shell)的路径。这个变量的值通常是指向用户首选 Shell 程序的绝对路径,比如 /bin/bash/bin/zsh、或 /bin/sh 等。

在这里插入图片描述

PWD

PWD环境变量保存当前路径
在这里插入图片描述

除了echo这种查询方式还有什么查询方式吗?—答案是有的,用函数来查。
在这里插入图片描述

有一个函数叫getenv,这个函数可以环境变量,我们来掩饰一下。

#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[],char *env[])
{printf("PWD:%s\n",getenv("PWD"));return 0;
}

在这里插入图片描述
可以看见也可以查看当前路径。

OLDPWD

OLDPWD 环境变量在 Linux 系统中表示上一次工作目录的路径。当用户在终端中更改目录时(使用 cd 命令),系统会将当前目录的路径存储在 OLDPWD 中。这样,用户可以快速返回之前的目录。

平时我们cd -就是通过这个环境变量来实现的。

本地变量

平时我们肯定这样干过。
在这里插入图片描述
这样在命令行上设置变量,这样设置的是环境变量吗?
可以看见这样其实也是可以用echo去查的。
在这里插入图片描述
其实这是本地变量,而不是环境变量。
用一张图来理解什么是本地变量什么是环境变量:
在这里插入图片描述

其实在bash进程中形成了三张表,还有一张是本地变量表。
shell除了维护环境变量表还会维护本地变量表,shell会在自己内部malloc一段空间,然后将诸如上面的"i=1"这样的字符串存在malloc出来的这段空间中,然后查找的时候shell会根据=的前后去匹配这个变量
如何将本地变量转换成环境变量呢?
在这里插入图片描述
有一个命令是export可以将本地变量设置为环境变量,从上面的表可以看出,将本地变量设置为环境变量的本质其实是将本地变量表中指向的字符重新连接到env[]上,就这么简单
还有一个命令是取消环境变量是unset,是取消设置环境变量。

总结

在 Linux 中,命令行参数和环境变量作为系统和应用之间的桥梁,提供了灵活且高效的配置和交互方式。通过理解这些机制的内部原理,不仅可以更深入地掌握 Linux 系统的工作方式,还可以优化脚本编写和应用配置的能力。在日常使用中,充分利用环境变量和命令行参数,能够大幅提高工作效率,打造出更加符合需求的操作体验。希望这篇文章能帮助你更好地理解和运用这些基础概念,迈向更高效的 Linux 使用之路!

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

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

相关文章

leetcode57:插入区间

给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表 intervals&#xff0c;其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束&#xff0c;并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval [start, end] 表示另一个区间的开始和…

探熵科技|以科技赋能销售,创造卓越业绩。

发展 在当今时代&#xff0c;AI 和大数据技术迅猛发展&#xff0c;各行业与大数据技术的融合已成为推动企业发展的重要力量。 天眼销 探熵科技作为一家专注于商业数据服务的专业公司&#xff0c;始终致力于为企业和个人提供高质量的数据解决方案。我们凭借深厚的技术实力和对…

Nginx+Lua脚本+Redis 实现自动封禁访问频率过高IP

1 、安装OpenResty 安装使用 OpenResty&#xff0c;这是一个集成了各种 Lua 模块的 Nginx 服务器&#xff0c;是一个以Nginx为核心同时包含很多第三方模块的Web应用服务器&#xff0c;使用Nginx的同时又能使用lua等模块实现复杂的控制。 &#xff08;1&#xff09;安装编译工具…

批量剪辑视频软件源码搭建全解析,支持OEM

一、引言 在当今数字化内容创作的时代&#xff0c;视频制作的需求呈爆发式增长。无论是社交媒体上的短视频创作者&#xff0c;还是专业的视频制作团队&#xff0c;都面临着大量视频剪辑的任务。批量剪辑视频软件应运而生&#xff0c;它能够显著提高视频剪辑的效率&#xff0c;满…

C语言笔记(指针题目)例题+图解

本文分为两部分 &#xff0c;第一部分为数组、字符串、字符指针在sizeof和strlen中的辨析&#xff0c;第二部分是一些笔试题目。若有错误&#xff0c;请批评指正。 目录 1.第一部分 1.1.数组名的使用 1.1.1一维整型数组在sizeof中的使用 1.1.2一维字符数组在sizeof中的使用…

015:地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework安装教程

摘要&#xff1a;本文详细介绍地理信息系统开发平台ArcGIS Engine10.2与ArcGIS SDK for the Microsoft .NET Framework的安装流程。 一、软件介绍 ArcGIS Engine 10.2是由Esri公司开发的一款强大的GIS&#xff08;地理信息系统&#xff09;开发平台。该软件基于ArcGIS 10.2 fo…

华为手机卸载系统应用的方法

摘要&#xff1a; 1.手机环境&#xff1a;手机需要开启开发者模式并使用usb连接电脑&#xff0c;并选择文件传输模式 2.电脑环境&#xff1a;使用鸿蒙工具箱进行傻瓜操作或安装adb工具进行命令卸载 3.鸿蒙工具箱和adb工具本质都是使用adb shell pm uninstall -k --user 0 xx…

大数据中心年度数据运营服务项目实施技术方案(183页WORD)

文档介绍&#xff1a; 本大数据中心年度数据运营服务项目实施技术方案&#xff0c;通过构建高效的数据集成与治理平台、数据分析平台以及创新的数据服务模式&#xff0c;旨在为企业内外部用户提供更加精准、高效的数据支持。同时&#xff0c;注重安全与合规保障&#xff0c;确…

【linux网络编程】| socket套接字 | 实现UDP协议聊天室

前言&#xff1a;本节内容将带友友们实现一个UDP协议的聊天室。 主要原理是客户端发送数据给服务端。 服务端将数据再转发给所有链接服务端的客户端。 所以&#xff0c; 我们主要就是要实现客户端以及服务端的逻辑代码。 那么&#xff0c; 接下来开始我们的学习吧。 ps:本节内容…

TIFS-2024 FIRe2:细粒度表示和重组在换衣行人重识别中的应用

总体结论 本文提出了一种新的细粒度表示与重构&#xff08;FIRe2&#xff09;框架&#xff0c;用于解决布变人重识别问题。通过细粒度特征挖掘和属性重构&#xff0c;FIRe2在不依赖任何辅助信息的情况下&#xff0c;实现了最先进的性能。该方法在多个基准数据集上取得了显著的…

一款专业获取 iOS 设备的 UDID 工具|一键获取iPhone iPad设备的 UDID

什么是UDID&#xff1f; UDID&#xff0c;是iOS设备的一个唯一识别码&#xff0c;每台iOS设备都有一个独一无二的编码&#xff0c;这个编码&#xff0c;我们称之为识别码&#xff0c;也叫做UDID&#xff08; Unique Device Identifier&#xff09; 扫描后系统提示输入密码&am…

HTML--浮动布局练习

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title><style>/* 整个浏览器页…

ES6 变量的解构赋值

数组的解构赋值 对象的解构赋值 字符串的解构赋值

利用游戏引擎的优势

大家好&#xff0c;我是小蜗牛。 在当今快速发展的游戏产业中&#xff0c;选择合适的游戏引擎对开发者来说至关重要。Cocos Creator作为一款功能强大且灵活的游戏引擎&#xff0c;为开发者提供了丰富的工具和资源&#xff0c;使他们能够高效地开发出优秀的游戏。本文将探讨如何…

Python+Selenium+Pytest+POM自动化测试框架封装(完整版)

&#x1f345; 点击文末小卡片 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1、测试框架简介 1&#xff09;测试框架的优点 代码复用率高&#xff0c;如果不使用框架的话&#xff0c;代码会显得很冗余。可以组装日志、报告、邮件等一些高…

【鸿蒙HarmonyOS实战:通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程(邀请码)方式教程详解】

鸿蒙HarmonyOS实战&#xff1a;通过华为应用市场上架测试版App实现HBuilder X打包的UniApp项目的app转hap教程&#xff08;邀请码&#xff09;方式详解 在使用uniapp打包的鸿蒙项目的过程中&#xff0c;由于生成的是app文件&#xff0c;而hdc传给鸿蒙HarmonyOS系统需要的是hap文…

【Apache Zookeeper】

一、简介 1、场景 如何让⼀个应⽤中多个独⽴的程序协同⼯作是⼀件⾮常困难的事情。开发这样的应⽤&#xff0c;很容易让很多开发⼈员陷⼊如何使多个程序协同⼯作的逻辑中&#xff0c;最后导致没有时间更好地思考和实现他们⾃⼰的应⽤程序逻辑&#xff1b;又或者开发⼈员对协同…

名词(术语)了解--SSR/CSR

名词&#xff08;术语&#xff09;了解–SSR/CSR 什么是服务器端渲染(SSR)? 服务器端渲染是指由服务器生成完整的 HTML 页面&#xff0c;然后发送给客户端的过程。 这与客户端渲染&#xff08;CSR&#xff09;形成对比&#xff0c;后者主要依赖浏览器端的 JavaScript 来渲染…

有趣智力题(非编程题)

目录 赛马烧香问题 赛马 题目描述: 一共有36匹马 6个跑道 在没有计时器的情况下 请问: 最少进行多少次赛马 可以确定前三名? 答案:8次 图解思路: 注意下图写错了 注释没写错 图画错了 正确的是下图 烧香问题 题目描述: 有两根香 材质不均匀 但是每一根香 烧完都需要1h 请利用…

学习threejs,使用粒子实现下雪特效

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.Points简介1.11 ☘️…