目录
命令行参数与环境变量
命令行参数
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 | 用户命令(可执行程序) | ls,cd,grep,find |
| 2 | 系统调用(内核提供的接口) | read,write,open,fork |
| 3 | 库函数(C 标准库) | printf,malloc,strcpy |
库函数与系统调用的对比
| 维度 | 系统调用 | 库函数 |
|---|---|---|
| 运行空间 | 内核态(Kernel Mode) | 用户态(User Mode) |
| 调用开销 | 大(需上下文切换) | 小(普通函数调用) |
| 实现者 | 操作系统内核 | 语言库(如 glibc)或应用程序 |
| 例子 | read()、write()、open()、fork() | printf()、scanf()、fread()、strcpy() |
| 是否缓冲 | 无缓冲(直接操作内核) | 通常有缓冲(如 stdio 缓冲) |
| 执行速度 | 慢 | 快 |
博主吐血回顾重构整理 求关注
o(╥﹏╥)o