Linux进程-命令行参数和环境列表

C语言命令行参数与环境变量详解
本文深入解析C语言中main函数的参数argc、argv及envp的作用,阐述了如何通过命令行参数和环境变量与程序进行交互,包括在不同场景下获取和使用这些参数的方法。

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

               

命令行参数

在C中,main函数有很多的变种,比如

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

在很长一段时间里(特别是在windows下),我都不清楚后面两种main函数中这么多参数有什么用,直到转到linux下,才明白了这些参数并不是多余的。


int main(int argc, char *argv[])。这两个参数也就是我们在命令行中跟在要执行程序名后面的参数。比如 ./necho hello world。参数的个数存储在argc中(在这个例子中是3,necho也算参数),参数的内容存储在argv指向的一个二维数组中(necho存储在二维数组中的第一个位置),参数名后面都以NULL结尾。

使用argv[0]的一点小技巧

在实际工作中,我们可以对一个程序创建多个不同名称的链接。当从不同名称的链接执行该程序时,我们在程序中可以通过argv[0]知道到底是哪个链接在执行该程序,这样我们就可以调用程序的不同部分来执行。这样做的好处是,同一个程序在不同链接名的调用下,表现出不同程序的特性。

 

几种不使用main函数参数来获得命令行参数的用法(不可移植):

1.在linux系统中,可以通过/proc/PID/cmdline来获得命令行参数,但是参数之间的空格被忽略。比如上面例子中,如果cat /proc/PID/cmdline 将会得到./nechohelloworld。如果在程序中可以通过下面代码来获得命令名:

       int fd = open(“/proc/self/cmdline”,  O_RDONLY);

       read(fd, buff, 100);

2.在C库中,为了使程序能知道命令的路径,提供了两个全局变量program_invocation_name, program_invocation_short_name(定义在<errno.h>,必须在程序中定义_GNU_SOURCE)。第一个全局变量提供了命令的完整路径,而第二个只提供了一个命令名。比如/home/share/src/necho和necho。

通常情况下,我们的命令行参数不会多到溢出,不过了解存储该参数的空间大小对编程也没什么坏处。我们可以通过ARG_MAX(定义在<limits.h>)这个宏或者sysconf(_SC_ARG_MAX)系统调用来了解参数空间大小(该空间存储命令行参数和环境变量)。在linux系统上,ARG_MAX曾经被固定的设置为32个页的大小。但是从2.6.32起,该存储空间的大小被定义为RLIMIT_STACK的四分之一。

 

环境变量

每个进程都有相关联的环境列表(Environment List),环境列表由多个环境字符串组成。环境字符串被定义成name=value格式。name叫做环境变量(Environment Variable)。

 

当一个进程被创建时,该进程继承父进程的环境列表。这个特性可以作为父进程和子进程通信的一种方法。比如,当父进程要创建子进程时,可以先设置某个环境变量,子进程随后在自己的环境列表中读取该环境变量。不过这种通信是单向的(one-way)和一次性的(once-only),子进程在创建后,就完全拥有和父进程独立环境列表了。程序可以通过检查环境变量来改变程序的特性(像使用命令行参数一样)。

 

环境变量通常在shell中使用,在shell中创建的进程都继承了shell的环境列表。通常在bash下,我们像下面这样使用环境变量:

export SHELL = /bin/bash

如果只是想设置某一个程序的环境变量,可以这样使用:

name1=var1 name2=var2 nameN=varN program

使用printenv显示当前的环境列表:

$printenv

SHELL=/bin/bash

HOME=/home/ddb

PATH=/usr/local/bin:/usr/bin:/bin:

可以通过cat /proc/PID/environ来查看进程环境列表。

 

程序中如何使用环境列表

1.通过全局变量char **environ。environ和argv很相似。也可以通过

int main(int argc, char *argv[], char *envp[])中的envp来访问。

2.使用程序提供的API。

char *getenv(const char *name)

注意点:

a.该函数返回指定环境变量的字符值。

b.不要直接修改返回值,因为在类UNIX的大部分实现中,返回指针实际上是指向环境字符串中的value部分的。如果要改变该值,使用setenv()或putenv()。

c.当程序得到一个返回指针后,要用一个私有buff来保存该值。因为在某些实现中,该函数内部使用一个静态buff来保存需要返回的值,这使得在下一次函数被调用后,静态buff中的值被其他值覆盖。

 

int putenv(char *string)

注意点:

1.成功返回-0,失败返回-非0(不是-1)。

2.string的格式为”name=value”。

3.不要把string声明成自动变量,string将成为环境列表的一部分,也就是说,该程序不会复制string到环境列表中,而是把string当做列表的一部分,当程序中改变string,会影响该进程的环境变量。

4.使用该函数通常是父进程想让它所创建的子进程继承某个改变的环境变量。或者是想让自己根据改变的环境变量来改变程序的特性(先改变某些环境变量,然后执行exec()函数群来调用自己,程序重启,然后根据这些改变的环境变量来改变程序运行的特性)。

int setenv(const char *name, const char *value, int overwrite)

int unsetenv(const char *name)

注意点:

1.setenv()会创建一个新的buff来存储参数“name=value“(跟putenv对比),我们没必要再name后面或value前面添加”=”号,因为在该函数中会自动添加。

2.只有在overwrite为非0,环境变量才会改变。

 

#define _BSD_SOURCE

int clearenv(void)

注意点:

1.该函数清除整个环境列表。也可以通过environ=NULL来清除。

2.当该函数跟setenv()一起使用时,会产生内存泄露。因为clearenv()不会清除setenv()分配的内存。这两个函数不会频繁的调用,所有通常不是什么大问题。

ABI的讨论

Application Binary Interface是一组规则,它指定了一个二进制程序在运行时如何和内核、库交换信息。ABI指定了交换信息的寄存器和栈位置。一个ABI兼容的程序被编译后,它就可以在所有ABI兼容的系统上运行了。


           

分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

Linux系统中,命令行参数选项是与命令行工具应用程序交互的重要方式,它们让用户可以根据具体需求灵活地控制程序的行为。 ### 命令行参数 命令行参数是紧跟在可执行命令之后,以空格分隔的字符串。例如,在 `cp source_file destination_file` 命令中,`source_file` `destination_file` 就是命令行参数,分别指定了要复制的源文件目标文件的路径。 在C语言编写的程序中,`main` 函数用于接收命令行参数,其标准定义为 `int main(int argc, char *argv[])`。其中,`argc` 表示传递给程序的命令行参数个数(包括程序名称本身),`argv` 是一个指针数组,每个指针指向一个字符串,`argv[0]` 为程序名称,后续元素依次为命令行参数 [^1][^3]。 以下是一个简单的C语言示例,用于打印所有命令行参数: ```c #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; } ``` ### 命令行选项 命令行选项是一种特殊的命令行参数,用于修改程序的行为。常见的形式有短选项(如 `-h`)长选项(如 `--help`)。短选项通常以单个连字符开头,后面跟一个字母;长选项以两个连字符开头,后面跟一个单词。例如,`ls -l` 中的 `-l` 是短选项,用于以长格式显示文件列表;`ls --color=auto` 中的 `--color=auto` 是长选项,用于自动根据终端支持情况显示彩色输出 [^1][^2][^5]。 ### 命令行参数选项的解析 在编写程序时,需要对命令行参数选项进行解析,以确定用户的具体需求。在C语言中,可以使用 `getopt` 或 `getopt_long` 函数来解析短选项长选项。以下是一个使用 `getopt` 函数解析短选项的示例: ```c #include <stdio.h> #include <unistd.h> int main(int argc, char *argv[]) { int opt; while ((opt = getopt(argc, argv, "ab:c")) != -1) { switch (opt) { case 'a': printf("Option -a is set.\n"); break; case 'b': printf("Option -b is set with argument %s.\n", optarg); break; case 'c': printf("Option -c is set.\n"); break; default: fprintf(stderr, "Usage: %s [-a] [-b argument] [-c]\n", argv[0]); return 1; } } return 0; } ``` ### 命令行参数选项的应用场景 - 文件操作:许多文件操作命令,如 `ls`、`cp`、`mv`、`rm` 等,都支持通过命令行选项来控制操作的细节,如显示隐藏文件、递归操作等。 - 网络操作:网络工具,如 `ping`、`traceroute`、`ssh` 等,也可以使用命令行参数选项来指定目标地址、端口号、超时时间等。 - 系统管理:系统管理命令,如 `ps`、`top`、`df` 等,通过命令行选项可以获取不同的系统信息,如进程状态、系统资源使用情况等。 ### 注意事项 - 命令行参数之间用空格分隔,如果参数本身包含空格,需要用引号将整个参数括起来。 - 不同的程序对命令行参数选项的处理方式可能不同,使用前需要查看相应的帮助文档。 - 在编写程序时,要对用户输入的命令行参数选项进行合法性检查,避免因非法输入导致程序崩溃或产生不可预期的结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值