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

目录

一、命令行参数:

二、环境变量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导入环境变量,即添加到环境变量表中,此时才能获取

相关推荐
栈老师不回家10 分钟前
Vue 计算属性和监听器
前端·javascript·vue.js
前端啊龙15 分钟前
用vue3封装丶高仿element-plus里面的日期联级选择器,日期选择器
前端·javascript·vue.js
荒Huang17 分钟前
Linux挖矿病毒(kswapd0进程使cpu爆满)
linux·运维·服务器
一颗松鼠20 分钟前
JavaScript 闭包是什么?简单到看完就理解!
开发语言·前端·javascript·ecmascript
小远yyds40 分钟前
前端Web用户 token 持久化
开发语言·前端·javascript·vue.js
吕彬-前端2 小时前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱2 小时前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai2 小时前
uniapp
前端·javascript·vue.js·uni-app
hjjdebug2 小时前
linux 下 signal() 函数的用法,信号类型在哪里定义的?
linux·signal
其乐无涯2 小时前
服务器技术(一)--Linux基础入门
linux·运维·服务器