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

news2024/11/27 16:33:35

在这里插入图片描述

文章目录

  • 命令行参数
    • 什么是命令行参数
    • 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.coloradmin.cn/o/2227861.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Pytest-Bdd-Playwright 系列教程(4):基于敏捷的通用步骤定义

Pytest-Bdd-Playwright 系列教程&#xff08;4&#xff09;&#xff1a;基于敏捷的通用步骤定义 前言一、项目结构二、通用步骤定义三、特性文件设计四、测试脚本实现五、运行测试总结 前言 在敏捷迭代中&#xff0c;为了适应快速、高频的交付&#xff0c;自动化测试框架的设计…

银行信贷风控专题:Python、R 语言机器学习数据挖掘应用实例合集:xgboost、决策树、随机森林、贝叶斯等...

全文链接&#xff1a;https://tecdat.cn/?p38026 分析师&#xff1a;Fanghui Shao 在当今金融领域&#xff0c;风险管控至关重要。无论是汽车贷款违约预测、银行挖掘潜在贷款客户&#xff0c;还是信贷风控模型的构建&#xff0c;以及基于决策树的银行信贷风险预警&#xff0c;…

Ubuntu22.04环境搭建MQTT服务器

官网&#xff1a; https://mosquitto.org 1.引入库 sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa2.升级安装工具 sudo apt-get update 3.安装 sudo apt-get install mosquitto 4.安装客户端 sudo apt-get install mosquitto-clients5.添加修改配置文件 进…

Python | Leetcode Python题解之第519题随机翻转矩阵

题目&#xff1a; 题解&#xff1a; class Solution:def __init__(self, m: int, n: int):self.m mself.n nself.total m * nself.map {}def flip(self) -> List[int]:x random.randint(0, self.total - 1)self.total - 1# 查找位置 x 对应的映射idx self.map.get(x,…

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

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

Windows 下实验视频降噪算法 MeshFlow 详细教程

MeshFlow视频降噪算法 Meshflow 视频降噪算法来自于 2017 年电子科技大学一篇高质量论文。 该论文提出了一个新的运动模型MeshFlow&#xff0c;它是一个空间平滑的稀疏运动场 (spatially smooth sparse motion field)&#xff0c;其运动矢量 (motion vectors) 仅在网格顶点 (m…

随机采样方法之逆变换采样

抽样或采样是指从目标总体中抽取出部分个体也就是样本&#xff0c;通过对样本的属性或特征进行分析&#xff0c;以此对总体进行评估。采样作为一种重要的数据分析方法&#xff0c;在深度学习、渲染等诸多方面具有广泛的应用。本文将回顾一种基本的采样方法即逆变换采样。 一、…

国自然地学部立项名单(2021-2023年)和标书范本(2007-2017年33份)-最新出炉 附下载链接

国自然地学部立项名单&#xff08;2021-2023年&#xff09;和标书范本&#xff08;2007-2017年33份&#xff09; 下载链接-点它&#x1f449;&#x1f449;&#x1f449;&#xff1a; 国自然地学部立项名单&#xff08;2021-2023年&#xff09;和标书范本&#xff08;2007-201…

C++之多态的深度剖析

目录 前言 1.多态的概念 2.多态的定义及实现 2.1多态的构成条件 2.1.1重要条件 2.1.2 虚函数 2.1.3 虚函数的重写/覆盖 2.1.4 选择题 2.1.5 虚函数其他知识 协变&#xff08;了解&#xff09; 析构函数的重写 override 和 final关键字 3. 重载&#xff0c;重写&…

信息安全数学基础(34)正规子群和商群

正规子群详述 定义&#xff1a; 设G是一个群&#xff0c;H是G的子群。若H的左陪集与右陪集总是相等&#xff08;即对任何的a∈G&#xff0c;都有aHHa&#xff09;&#xff0c;则称H是G的正规子群或不变子群&#xff0c;记为H⊴G。 性质&#xff1a; 平凡性&#xff1a;任何群G…

日期选择简化版今日、本周、本月、本季度、本年

function 未来之窗_时间_现在() {let date new Date(),year date.getFullYear(), //获取完整的年份(4位)month date.getMonth() 1, //获取当前月份(0-11,0代表1月)strDate date.getDate() // 获取当前日(1-31),小时 date.getHours(),分钟 date.getMinutes();if (month &…

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

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

Android Input的流程和原理

Android Input事件机制 Android系统是由事件驱动的&#xff0c;而Input是最常见的事件之一&#xff0c;用户的点击、滑动、长按等操作&#xff0c;都属于Input事件驱动&#xff0c;其中的核心就是InputReader和InputDispatcher。InputReader和InputDispatcher是跑在system_serv…

Manus在虚拟现实仿真模拟中的应用案例分享

Manus虚拟现实手套作为一种高精度的人机交互设备&#xff0c;在仿真模拟领域展现出了巨大的应用潜力。通过提供实时、准确的手指动作捕捉数据&#xff0c;Manus手套为多个行业带来了前所未有的仿真体验&#xff0c;推动了技术发展和应用创新。 技术特点 1. 高精度手指跟踪 Manu…

windows 驱动实例分析系列: NDIS 6.0的Filter 驱动改造(四)

驱动的测试代码解读 1. 打开设备对象: // 1. 打开底层设备对象HANDLE hDevice CreateFile(L"\\\\.\\NDISFilter", // 设备名称GENERIC_READ | GENERIC_WRITE, // 访问权限0, // 不共享NULL, // 默认安全属性OPEN_EXISTING, // 打开现有设备0, // 无特殊标志NULL /…

加强版 第四节联通组件分析与演示

得到二值图像的目的是为了后面的分析 基本概念解释 -图像联通组件 -四邻域与八邻域联通 ccl联通组件标记 通过四邻域和八邻域来对图像进行边缘寻找与噪声处理的功能 常见算法来寻找联通组件 -基于像素扫描方法 -基于块扫描的方法 -两步法扫描 API: OpenCV中支持连通组件…

闯关leetcode——232. Implement Queue using Stacks

大纲 题目地址内容 解题代码地址 题目 地址 https://leetcode.com/problems/implement-queue-using-stacks/description/ 内容 Implement a first in first out (FIFO) queue using only two stacks. The implemented queue should support all the functions of a normal …

【Unity基础】初识UI Toolkit - 编辑器UI

&#xff08;本文所需图片在文章上面的资源中&#xff0c;点击“立即下载”。&#xff09; 本文介绍了如何通过UI工具包&#xff08;UI Toolkit&#xff09;来创建一个编辑器UI。 一、创建项目 1. 打开Unity创建一个空项目&#xff08;任意模板&#xff09;&#xff0c;这里我…

什么?Flutter 又要凉了? Flock 是什么东西?

今天突然看到这个消息&#xff0c;突然又有一种熟悉的味道&#xff0c;看来这个月 Flutter “又要凉一次了”&#xff1a; 起因 flutter foundation 决定 fork Flutter 并推出 Flock 分支用于自建维护&#xff0c;理由是&#xff1a; foundation 推测 Flutter 团队的劳动力短缺…

windows文件实时同步

在现今这个高效运转的工作时代&#xff0c;数据同步与备份的重要性愈发凸显。特别是对于Windows用户&#xff0c;实现文件在不同设备间的实时流转&#xff0c;不仅能够显著提升工作效率&#xff0c;更是数据安全的一道重要防线。接下来&#xff0c;我们将深入剖析Windows文件实…