环境变量与地址

一、基本概念:

环境变量一般是指在操作系统中用来指定操作系统运行的环境的一些参数。就比如在写C代码时,链接时我们并不知道链接的东静态库在哪里,但是照样连接成功,原因是有相关环境变量帮助编译器进行查找。

常见环境变量:

PATH:指定命令的搜索路径

HOME:指定用户的主工作目录(即用户登录到Linux系统中的默认路径)

SHELL:当前shell,它的值通常是/bin/bash

系统存在环境变量PATH来帮助系统找到二进制文件,告诉系统去哪些路径下找二进制文件。

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

	return 0;
}

main函数里的argv\[\]其实就是把命令行以空格作为分隔符然后填入指针数组当中。argv\[\]是个变长数组。第一个字符是./code 就把./code这个字符串的地址填入argv0,以此类推。也就是命令行参数依次变成子串放在数组里,放了多少个由argc来记录。

平时用的命令本质上是可执行程序,这个命令一般也是C语言写的。

cpp 复制代码
#include <stdio.h>
int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("Usage: %s [-a|-b|-c]", argv[0]);
	}

	return 0;
}

完善一下:

cpp 复制代码
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
	if (argc != 2)
	{
		printf("Usage: %s [-a|-b|-c]\n", argv[0]);
        return 1;
	}

	const char* arg = argv[1];

	if (strcmp(arg, "-a") == 0)
	{
		printf("这是功能1\n");
	}
	else if (strcmp(arg, "-b") == 0)
	{
		printf("这是功能2\n");
	}
	else if (strcmp(arg, "-c") == 0)
	{
		printf("这是功能3\n");
	}
	else
		printf("Usage: %s [-a|-b|-c]", argv[0]);

	return 0;
}

这样子就类似输入命令比如ls -a,ls -l,命令行参数用途是可以让一个程序通过选项实现不同的子功能。main函数的命令行参数是实现程序不同子功能的方法。

进程启动时有一张表叫argv表,用来支持实现选项功能。

用env查所有环境变量。归根节底在系统内找到一个命令或某个二进制文件默认是在环境变量path所对应的子路径中一个一个找的。对PATH进行赋值就可以直接变成命令。但是ls这样系统的命令找不到了。这是因为直接赋值就把原来PATH里的路径给覆盖了。

二、如何理解环境变量:登录的时候形成一张表,叫环境变量表,是一个指针数组

输入ls -a先被bash拿到,然后就拆分,先构建命令行参数表,再用ls这个命令在环境变量表中找到PATH,再根据路径拼上程序名,然后找到了创建子进程

bash内部有两张表,命令行参数表和环境变量表 。

环境变量最开始是从配置文件来的。

和环境变量的相关命令:

echo:显⽰某个环境变量值

export: 设置⼀个新的环境变量

env: 显⽰所有环境变量

unset: 清除环境变量

set: 显⽰本地定义的shell变量和环境变量

三、获取环境变量的方法:

1.和环境变量的相关命令:

echo:显⽰某个环境变量值

export: 设置⼀个新的环境变量

env: 显⽰所有环境变量

unset: 清除环境变量

set: 显⽰本地定义的shell变量和环境变量

比如要导入一个环境变量叫MYENV=11223344,就写export MYENV=11223344,这样就可以让系统在环境变量表里写入MYENV字符串了,然后再查找,就会出现MYENV=11223344。

清除就写unset MYENV。

2.main函数的参数:有三个。

方法一:int argc, char *argv\[\], char *env\[\],后面两个是命令行参数表和环境变量表,是由系统解析好之后传给main函数的,所以可以在main函数里遍历env来获取环境变量。

cpp 复制代码
int main(int argc, char *argv[], char *env[])
{
    (void)argc;
    (void)*argv;

    for (int i = 0; env[i]; i++) // 遍历到结尾是NULL循环自己会结束
    {
        printf("env[%d]->%s\n", i, env[i]);
    }

    return 0;
}

方法二:getenv:写一个程序只能我执行其他人执行不了。

cpp 复制代码
int main(int argc, char *argv[])
{
    (void)argc;
    (void)*argv;

    const char *who = getenv("USER");
    if(who==NULL)
        return 1;

    if(strcmp(who,"lxy")==0)//比较必须是某个用户才能运行
    {
        printf("程序正常逻辑");
    }
    else 
    {
        printf("Only lxy");
    }

    return 0;
}

方法三:通过第三方变量environ获取。

cpp 复制代码
int main(int argc, char *argv[])
{
    (void)argc;
    (void)*argv;

    extern char **environ;
    for (int i = 0;; environ[i]; i++)
    {
        printf("environ[%d]->%s\n", i, environ[i]);
    }

    return 0;
}

四、环境变量的特性:全局性,可以被子进程继承下去

环境变量在BASH里,内建命令,执行时不需要创建子进程,而是bash自己执行,bash自己调用函数或者系统自己调用

直接在命令行当中定义本地变量,bash会记录两套变量,环境变量和本地变量,本地变量不会被子进程继承,只能在bash内部使用

相关推荐
来者皆善14 小时前
ZYNQ linux上使用 USB CDC ACM
linux·运维·服务器
Dawn-bit16 小时前
Linux磁盘分区与Swap和磁盘故障查询
linux·运维·服务器·网络·云计算
无足鸟ICT17 小时前
【RHCA+】$[]
linux·运维·服务器
运维技术小记18 小时前
国产化环境配置 VNC 远程桌面:麒麟 V10 实战
linux·运维·服务器
xiaoye-duck18 小时前
《Linux系统编程》Linux 系统多线程(八): C++ 高并发线程池全链路深度解析与从零手撕实现
linux·c++·线程池
寒水馨19 小时前
Linux下载、安装protobuf-v35.1(附安装包protoc-35.1-linux-x86_64.zip)
linux·运维·服务器·google·序列化·protobuf·protoc
王琦031819 小时前
Linux的文件管理
linux·运维·服务器
☆凡尘清心☆19 小时前
CentOS Stream 9 Redis 7.2.7 源码编译一键安装脚本
linux·运维·redis·centos
Android系统攻城狮19 小时前
Linux PipeWire深度解析之pw_stream_new调用流程与实战(四十二)
linux·运维·服务器·音频进阶·pipewire音频进阶
蜉蝣fuyou19 小时前
VMware多版本安装包
linux·vmware·虚拟机