命令行参数、环境变量详解

目录

一、命令行参数:

二、环境变量PATH

1、理解什么是环境变量

2、常见环境变量和操作

3、整体理解环境变量,系统,程序

[4、如何获取环境变量(c语言)](#4、如何获取环境变量(c语言))

[(1)getenv() 函数](#(1)getenv() 函数)

[(2)使用 extern char **environ](#(2)使用 extern char **environ)

5、内建命令

特点和用法


一、命令行参数:

我们常写的main函数是可以带参数的

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

{

//...

return 0;

};

当我们在命令行输入带有main函数的程序时,

可以在程序的后面输入一些值

如图:

makefile文件:

cpp 复制代码
 myprocess:myprocess.c                                                                                                        
  2   gcc -o myprocess myprocess.c -std=c99 
  3 
  4 .PHNOY:clean
  5 clean:
  6   rm -f myprocess
~

c文件:

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

当你输入n个值,argc的大小就是n

对应的,就会开辟一个大小为n的argv数组

argv数组的最后一个位置是NULL

第一个位置argv[0]一定是程序名

那么这个有什么用处呢?

其实我们输入的命令行,本质是一行字符串:

这一行字符串的意义: 程序的路径 + 名称 和 该进程匹配的选项

例如:

ls -l

ls -a

ls -d

ls -dla

....

ls本质是一个程序,后面的-x代表这个程序的不同的功能

你在命令行输入ls

本质上和你自己执行一个自己写的 ./xxx.c 可执行程序没有任何区别

因此,为什么有命令行参数:
命令行参数的本质是交给我们程序的不同选项,用来定制不同的程序功能,程序命令中会携带很多选项

父进程的数据,默认能被子进程看到并访问

且命令行中启动的程序,都会变成进程,其实都是bash的子进程

因此,我们平常在命令行中输入的命令,就是默认输入给bash父进程的

而bash就叫做命令行解释器

因此,bash就会把输入的字符串解释成对应的信息表

而子进程是可以看到父进程的信息的

因此,父进程就可以把对应的参数,初始化为argc,和argv[],再传给对应的子进程执行

二、环境变量PATH

1、理解什么是环境变量

可是,为什么我们在运行自己的程序时,必须加上**./**

执行ls pwd等程序却不需要呢?

而执行程序,首先要找到命令的所在位置,然后加载到内存中,再运行

所以,我们可以这样理解:

ls等命令不需要路径,是不是因为bash已经知道了这个程序的路径呢?

而且这个路径以某种形式默认着

而我们自己写的程序,因为没有这种默认,所以bash不认识,所以必须要指明路径

是不是这个原因呢?

是的,没错,就是如此

而这个默认的形式,就是环境变量,PATH

在Linux中,存在一些全局的设置,这些设置告诉命令行解释器,应该去哪些路径寻找可执行程序

这样,就不需要专门的再加上一个./路径

PATH是一个一系列路径的组合:

在执行一个程序时,如果这个命令在PATH的默认路径上逐个搜寻,如果找到了

就直接加载到内存并执行

如果没有找到,就提示找不到命令

这也就是为什么,当你输入一个字符串命令的时候

本质上其实是输入一个程序

这个字符串要被bash命令行解释器解释,这也就是为什么bash叫做命令行解释器

解释的过程,其实就是在环境变量设置的默认路径中,寻找对应程序的过程

如果找不到对应的程序

这个时候,命令行就会提示如下:

找不到命令行,这就是原因!

查看环境变量:

cpp 复制代码
echo $PATH

(我这里用的是root用户,我们在使用自己的操作系统时,尽量不要使用root用户,因为权限太高,容易出事情)

那么,如果,我的程序也要像系统命令一样,不需要./就可以直接运行

怎么办?

很简单,比较简单粗暴的做法就是,直接cp我们的程序到/usr/bin/路径下

cpp 复制代码
cp XXX /usr/bin/ 

这样,就可以像系统命令一样直接运行了

例如:当我把我的可执行文件直接拷贝到/usr/bin环境变量路径下,我就可以直接像执行命令一样,直接运行我自己写的文件。

但是强烈不建议这样做

因为会污染系统的指令集

但是事实上,这种环境变量只是一个内存级别的

什么意思?

当系统退出后,操作系统数据和代码退出内存,那么你的设置也就随之消失了

这也就说明,最开始的环境变量并不是保存在内存中,而是存在操作系统的配置文件中

每一加载Linux操作系统,都会读取加载操作系统的配置文件的内容

所以,你在修改PATH的时候,修改的只是内存中的运行备份

而没有修改操作系统的配置文件的内容

那么,配置文件在哪里

在家目录下的:

bash_profile

bashrc

/etc/bashrc

那么,到底怎么加呢?

千万不敢这样加:

PATH = 某某某路径

这会导致,你直接篡改了整个环境变量,把原来系统的默认路径都直接修改了

这样,你原来的系统命令都不能用了

应该这样加:

cpp 复制代码
PATH = $PATH:/某某路径

因此,PATH是Linux下默认查找程序命令和路径,也是which查找命令指令的默认路径

2、常见环境变量和操作

查看所有环境变量:

cpp 复制代码
env

查看单个环境变量:

cpp 复制代码
echo $环境变量名

导进自定义环境变量:(如果不加export,叫做本地变量)

cpp 复制代码
export name=value (可以是数字、字符等)

删除环境变量:

cpp 复制代码
unset XXX

示例:

export mypath=1111#添加

env#全局查找

echo $mypath#单独查找

unset mypath #删除

env#全局查找

常见的环境变量:

HOME:家目录

PWD:当前路径,会动态跟进修改

HISTSIZE:历史命令记录(Linux默认1000条,我的显示是10000条)

SHELL:外壳程序

3、整体理解环境变量,系统,程序

bash进程启动的时候,默认会给子进程形成两张表:

argv[]命令行参数表:有用户输入命令行形成

env[]环境变量表:由操作系统的配置文件读取来形成

其中,bash通过某种方式将两张表交给子进程(其实是通过execvpe函数 ,在进程替换部分有)

所以,本质上,echo $PATH命令的执行

其实就是在env[]环境变量表(二级指针数组)进行遍历查找并打印出来的过程

再继续理解,其实export环境变量,其实就是再env[]环境变量表中添加一个字符串而已

其实,mian函数最多可以有三个参数:

int argc, char* argv[], char* env[]

环境变量具有系统级别的全局属性,因为环境变量本身可以被子进程继承

为什么被子进程继承就有全局属性呢?

因为bash是所有进程的父进程

4、如何获取环境变量(c语言)

(1)getenv() 函数:

函数原型:

char *getenv(const char *name);

功能:根据给定的环境变量名称 name,返回对应的环境变量值(字符串形式)。如果该环境变量不存在,则返回 NULL。

示例用法:(variable意为变量)

cpp 复制代码
#include <stdio.h>
#include <stdlib.h> // for getenv()

int main() {
    char *env_value = getenv("PATH");
    if (env_value != NULL) {
        printf("PATH environment variable: %s\n", env_value);
    } else {
        printf("PATH environment variable not found.\n");
    }
    return 0;
}

(2)使用 extern char **environ

功能:environ 是一个全局变量,它指向当前进程的环境变量数组 。可以遍历这个数组来获取所有的环境变量及其值。

示例用法:

cpp 复制代码
#include <stdio.h>
extern char **environ;

int main() {
    char **env = environ;
    while (*env != NULL) {
        printf("%s\n", *env);
        env++;
    }
    return 0;
}

注意:使用 environ 时,需要包含 <stdio.h> 头文件,但不需要额外的 <stdlib.h>。

5、内建命令

Linux内建命令(built-in commands)指的是直接由shell(如bash)内部实现并提供的命令,而不是通过调用外部可执行文件来执行。这些命令被编译进shell的可执行文件中,因此在调用它们时不需要创建新的进程,执行速度相比外部命令更快,并且对shell的控制能力更强。

特点和用法:

  1. 性能优势:由于内建命令不需要调用外部程序,因此执行速度通常比外部命令更快,特别是在频繁调用时能显著减少系统资源的消耗。

  2. 对shell的影响:内建命令可以更深入地影响和操作shell的状态和行为,例如改变shell的环境变量、控制shell的作业和进程、修改shell的行为等。

  3. 通常的内建命令:具体的内建命令会因不同的shell而有所差异

以下是bash shell中常见的内建命令示例:

内建命令 功能
cd 切换当前工作目录
echo 打印文本或变量到标准输出
alias 创建命令别名
export 设置环境变量
unset 删除环境变量或shell变量
exit 退出当前shell
jobs 显示当前作业(jobs)列表
fg 将后台作业切换到前台
bg 将作业置于后台运行
source 或 . 执行shell脚本并保持在当前shell环境中

export、echo等为内建命令

也就是说,这些命令是bash内部的一个函数

执行这些程序时,不需要创建子进程

而是bash直接调用内部的函数

因此,命令分为两种:一个是普通命令,一个是内建命令

80%的命令是普通命令,普通命令需要创建子进程

本地变量(即未用export命令添加的环境变量成为本地变量)只在本bash内部有效,无法被子进程继承下去,需要export导入环境变量,即添加到环境变量表中,此时才能获取

相关推荐
odoo-卜永13 分钟前
ubuntu22.04连接爱普生打印机型号L385
linux·经验分享·ubuntu
庸俗今天不摸鱼16 分钟前
【万字总结】前端全方位性能优化指南(十)——自适应优化系统、遗传算法调参、Service Worker智能降级方案
前端·性能优化·webassembly
黄毛火烧雪下23 分钟前
React Context API 用于在组件树中共享全局状态
前端·javascript·react.js
Apifox34 分钟前
如何在 Apifox 中通过 CLI 运行包含云端数据库连接配置的测试场景
前端·后端·程序员
一张假钞36 分钟前
Firefox默认在新标签页打开收藏栏链接
前端·firefox
高达可以过山车不行36 分钟前
Firefox账号同步书签不一致(火狐浏览器书签同步不一致)
前端·firefox
m0_5937581038 分钟前
firefox 136.0.4版本离线安装MarkDown插件
前端·firefox
掘金一周41 分钟前
金石焕新程 >> 瓜分万元现金大奖征文活动即将回归 | 掘金一周 4.3
前端·人工智能·后端
小麦嵌入式1 小时前
Linux驱动开发实战(十一):GPIO子系统深度解析与RGB LED驱动实践
linux·c语言·驱动开发·stm32·嵌入式硬件·物联网·ubuntu
三翼鸟数字化技术团队1 小时前
Vue自定义指令最佳实践教程
前端·vue.js