目录

命令行参数与环境变量

命令行参数

vim下的main()

环境变量

环境变量的应用举例

查询环境变量

全部查询

针对名称查询(常用的方式)

环境变量的更改

配置环境变量

进程:命令行参数及环境变量的关系

结论

获取环境变量

①getenv();

②environ();

本地变量

特性:

本地变量的删除:

本地变量->环境变量:

问题探讨(内建命令)

库函数与系统调用


重构了main()函数-参数、运行环境,基于Linux进程深度下的吐血整理~~

命令行参数与环境变量

命令行参数

一个命令可以通过 [选项] 来实现特定的功能。

像:ls -a 及ls  -a  -l

类似于以前使用的main()函数中你可能见过的l两种形态:

int main(int argc, char *argv[]);
int main(int argc, char **argv);

main()作为程序的入口,实际上我们也可以通过外部指定[选项]来传入并调用特定功能:

vim下的main()

vim内:

int main(int argc, char *argv[])
{
    //……
    return 0;
}

在bash:

# 执行命令
./a.out -l -a hello world 123

本质就是将"-l -a hello world 123"分别分割并传入argv[]

argc 5
argv[0] "./myprogram"(程序名)
argv[1] "-l"
argv[2] "-a"
argv[3] "hello"
argv[4] "world"
argv[5] "123"
argv[6] NULL(结束标志)

运行代码:

#include <stdio.h>

int main(int argc, char *argv[]) {
    printf("参数个数: %d\n", argc);
    
    for (int i = 0; i < argc; i++) {
        printf("argv[%d] = %s\n", i, argv[i]);
    }
    
    return 0;
}

makefile内:

  1 SRC=$(wildcard *.c)
  2 OBJ=$(SRC:.c=.o)
  3 CC=gcc -std=c99                                                                                                                 
  4 LFLAGS=-o
  5 FLAGS=-c
  6 RM=rm -f
  7 all:$(OBJ)
  8     $(CC) $^ $(LFLAGS) pc
  9 %.o:%.c
 10     $(CC) $(FLAGS) $< $(LFLAGS) $@
 11 .PHONY: clean
 12 clean:
 13     $(RM) pc $(OBJ)

运行:

环境变量

功能:环境变量是进程级[背景]配置。

特性 说明
本质 键值对(HOME=/home/wzb)
作用 配置环境运行环境,无需修改代码
继承性 子进程自动继承父进程的环境变量
作用范围 当前进程及其子进程

因此:环境变量具有全局特性,可被所有进程继承

“进程级”配置又是一位程序新引入的执行逻辑,大大增加代码的复杂度。就像C中引入条件语句一般,是跨越性进步。

环境变量的应用举例

查询环境变量

全部查询

env

会打印显示全部已配置环境变量:
格式为[环境变量名称]=[环境变量内容]

针对名称查询(常用的方式)

echo $[名称]      #例如:echo  $PATH

环境变量的更改

①[原名称]=[新的绝对路径]     #覆盖原路径
②[原名称]=$[原名称]:[拼接路径]      #简便地路径拼接

配置环境变量

增加环境变量:

export  [名称]=[内容]

删除环境变量:

unset  [名称]

进程:命令行参数及环境变量的关系

无需多言:
我们在VS2022下运行

#include<stdio.h>
int main(int argc, char* argv[], char* envp[])
{
	// envp是环境变量数组,格式为"KEY=val"
	for (char** env = envp; *env != NULL; env++)
	{
		printf("%s\n", *env);
	}
	return 0;
}

运行结果:

结果显而易见:环境变量全部显现。

结论

因此:自入进程开始我们就处于“命令行参数”+“环境变量”的配置环境。图示如下:

获取环境变量

①getenv();

头文件<stdlib.h>
函数原型:

char* getenv(const char* name);

使用:

输入环境变量的名称来获取指向环境变量值的指针/NULL 。   // "指向目录路径"

#include <stdio.h>
#include <stdlib.h>

int main() {
    char *path = getenv("PATH");
    char *home = getenv("HOME");

    printf("PATH: %s\n", path);
    printf("HOME: %s\n", home);
    
    return 0;
}

运行结果:

PATH: /usr/local/bin:/usr/bin:/bin
HOME: /home/wzb
②environ();

头文件:<stdlib.h>
函数原型:

extern char** environ;

二级指针型访问数据可使用下标直接访问

代码实现:

输出同样的结果:


本地变量

本地变量是定义于vim外bash内的变量。

特性:

不会被子进程继承。
定义时"="两侧不能加空格  #否则会被当做命令进行查询  像:i=10正确而i = 10就是错误的!!

本地变量的删除:

像环境变量一样:

unset [本地变量名]

本地变量->环境变量:

export [本地变量名称]

问题探讨(内建命令)

众所周知:Linux指令是bash进程下执行文件的子进程。

假如export指令是一般性指令,怎么做到的子进程指令处理内容到父进程呢?

实际上:export别于一般性指令,其本质是“内建命令”(build-in command)。
               其不需要创建子进程,而是让bash自己操作

库函数与系统调用

指令"man"的指定页查询:

1 用户命令(可执行程序) lscdgrepfind
2 系统调用(内核提供的接口) readwriteopenfork
3 库函数(C 标准库) printfmallocstrcpy

库函数与系统调用的对比

维度 系统调用 库函数
运行空间 内核态(Kernel Mode) 用户态(User Mode)
调用开销 大(需上下文切换) 小(普通函数调用)
实现者 操作系统内核 语言库(如 glibc)或应用程序
例子 read()write()open()fork() printf()scanf()fread()strcpy()
是否缓冲 无缓冲(直接操作内核) 通常有缓冲(如 stdio 缓冲)
执行速度

博主吐血回顾重构整理 求关注
o(╥﹏╥)o

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐