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

实用指南:【Linux 系统】命令行参数和环境变量

文章目录

  • 前言
  • 1. 命令行参数
  • 2. 环境变量
    • 2.1 概念
    • 2.2 进程中获取环境变量
    • 2.3 环境变量的操作
    • 2.4 内建命令
  • 总结

前言

我在bash命令行上执行一些指令的时候,例如:ls指令。我们可以让我们的指令带上选项!从而实现出来不同的功能,可是我们有没有想过为什么指令带上不同的选项之后,就可以实现不同的功能了呢?

在这篇文章中,小编和大家了解认识两个东西:

  1. 命令行参数

  2. 环境变量

1. 命令行参数

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

main函数也是有参数的:

  1. argc:是一个整型参数,代表数组的元素个数。
  2. argv:是一个指针,指向的是是一个char*一维数组的起始地址。

我们对于这两个参数还是保持着一种好奇心理,于是我们写出了下面这样的测试代码:

// 已经正确包含头文件
int main(int argc, char* argv[])
{
for(int i = 0; i < argc; ++i)
{
printf("[%d]: %s\n", i, argv[i]);
}
return 0;
}

我们编译运行一下,得到如下的结果:
在这里插入图片描述

  • 现象

    我们在命令行上的参数都被传给了我们启动的进程的main函数的参数(argv)

不妨现在,我们将我们的代码进行更改:

int main(int argc, char* argv[])
{
if(strcmp(argv[1], "-a") == 0)
{
printf("功能1...\n");
//实现功能
}
else if(strcmp(argv[1], "-b") == 0)
{
printf("功能2...\n");
}
else
{
printf("未实现该功能...\n");
//...
}
return 0;
}

我们来看我们的测试结果
在这里插入图片描述

  • 结论

    命令行上的选项我们可以通过给main函数参数的形式交给程序。程序内部可以通过解析判断指令的选项类型是否正确,从而给我们实现不同的功能

  • 问题:那么我们在命令行上启动的程序是如何传参交给main函数的呢?

    这个问题,我们在命令行启动的进程大多都是bash进程的子进程。我们bash进程在接受到用户的命令的时候可以进行判断,从而创建子进程,采用系统调用exec*系列进程替换接口,详情在进程控制),从而将我们的输入的命令行选项传参给子进程。

  • 为什么需要main函数有这样的参数呢?

    就是为我们的指令、工具、软件等提供命令行选项的服务!

2. 环境变量

学习Linux系统,必然需要了解的一个知识点就是环境变量。在进程等中都比较重要。

2.1 概念

2.2 进程中获取环境变量

  1. 第一种方法:我们刚刚已经谈到了,我们可以通过函数调用:getenv获取单条环境变量的value值。

  2. 第二种方法:main函数参数的第三个参数

    实际上,main函数还有第三个参数。原型如下:int main(int argc, char* argv[], char* env[])。最后一个参数就是指向的就是系统为每一个进程维护的一张环境变量表

我们可以尝试打印出来试试(一般最后一个参数为nullptr

// 正确包含头文件
int main(int argc, char* argv[], char* env[])
{
for(int i = 0; env[i] != NULL; ++i)
{
printf("[%d]:%s\n", i, env[i]);
}
return 0;
}

我们依然可以获得环境变量表

在这里插入图片描述

  • 上图有一个细节:此时我们设置的环境变量PATH还在!!

    在这里插入图片描述

    那么我们一定会有如下问题

    1. 我们在bash命令行上启动我们的进程,我们的进程环境变量表来自哪里?

      这个问题,上面的哪个示例也已经能窥探一二了:我们在bash上启动的进程都是子进程,所以当我们子进程在被启动的时候,环境变量表来源于我们的父进程bash。
      同样地,当我们的进程创建了一个子进程之后,我们创建的子进程就会得到来自我们父进程的环境变量表。为什么?因为环境变量表也是数据,子进程会共享父进程的代码和数据

    2. 环境变量表是谁传递参数的?编译器对这些参数是如何感知的?

      我们也能明白,在我们bash命令行启动进程的时候父进程就需要进行准备,当我们父进程创建子进程之后,采用函数调用exec*系列接口的时候,我们的Linux操作系统就会为我们传递参数!

      编译器(如 gcc)编译代码时,它不只是编译main函数。它会将一段特殊的启动代码 链接到可执行文件的开头。这段代码是用汇编和C语言写的,负责设置C程序运行所需的基本环境(在准备的时候就可以获取环境变量表的地址了,还有argc,argv等参数)。当我们通过exec*接口替换你的程序后,CPU指令指针首先指向的就是这段启动代码,而不是main函数。简单来说,main函数也是函数,也是在启动的时候被调用的

    3. 一般一个进程的环境变量表存储在进程地址空间的哪个位置?

      根据操作系统的视角来看,一般存储在一个进程地址空间的顶部。所以,环境变量表在进程的角度也是一个进程的数据
      在这里插入图片描述

  1. 第三种方法:采用全局变量extern char **environ。该全局变量被声明在:<unistd.h>

    在这里插入图片描述

  • 注意:在同一个进程中,第二三种方法获取到的表一定是同一个。在程序替换中会涉及到对环境变量表的替换。

2.3 环境变量的操作

我们也可以来了解一下如何设置环境变量和查看环境变量

  1. echo $name:显示环境变量名为name的value值。
  2. env:显示当前系统的所有环境变量。
  3. export:设置一个新环境变量。
  4. unset name:清除名为name的环境变量。
  5. set:显示本地自定义的shell变量和环境变量。
  • export

    在这里插入图片描述
    说明我们的环境变量已经设置成功了!

2.4 内建命令

原因也很简单,这涉及了一个命令的分类。

很显然,上面的echo指令是一个内建命令!

总结

我们需要了解:

  1. 一个程序是有两张表的:

    • 命令行参数表

    • 环境变量表

    我们可以简单理解为:由操作系统维护的两张表。在进程启动的时候需要传给进程。

http://www.jsqmd.com/news/17397/

相关文章:

  • 得帆AI aPaaS(AI低代码)1.0产品特性(4)-智能搭建(一)
  • 日记11
  • element 表单校验失败定位到指定元素
  • 腾讯企业邮箱管理
  • 2025年湖北武汉实验室设计哪家口碑好/哪家信誉好/哪家售后好?
  • 国产化Word处理控件Spire.Doc教程:用Java实现TXT文本与Word互转的完整教程
  • C# Avalonia 16- Animation- BombDropper
  • C# 使用NPOI生成Word文件
  • 2025年太阳能板定制厂家口碑排行榜单:权威推荐与选择指南
  • 2025年太阳能板定制厂家口碑排行榜前十强:专业评测与选择指南
  • Python3 statistics 模块
  • linux内核开发学习计划
  • 2025年湖北武汉实验室装修/实验室设计/实验室改造哪个厂家好
  • 能源AI天团:多智能体如何破解行业复杂任务 - 实践
  • 2025年AI搜索优化品牌推荐排行榜前十强深度解析
  • 2025年AI搜索优化品牌推荐排行榜:技术深度解析与选择指南
  • 2025年AI搜索优化品牌排行榜前十强权威发布
  • 直播回顾|PostgreSQL 18 六大新特性深度解析
  • 异常----Windows 已保护你的电脑:Microsoft Defender SmartScreen 阻止了无法识别的应用启动。运行此应用可能会导致你的电脑存在风险。
  • win10 开启大小核心调度--异类策略0~4介绍
  • Windows 已保护你的电脑:Microsoft Defender SmartScreen 阻止了无法识别的应用启动。运行此应用可能会导致你的电脑存在风险。
  • 深入解析:Thinkphp-Laravel467 小程序校运会高校运动会管理系统
  • 恒生电子面经准备 - 详解
  • 082_尚硅谷_单分支双分支课堂练习(2)
  • 把“扔硬币”搬到互联网:一文看懂 AB 测试的底层逻辑 - 指南
  • 实用指南:IEC 60364-7-722-2018低压电气装置中电动车供电安全要求标准介绍
  • 记录下,cadence17.4 PCB封装更新方法
  • c#设计模式—访问者模式 - 教程
  • springboot使用aop切面,记录日志
  • 【整活】OI的那些奇妙小操作(Part 1)