execve的用法举例

execve的“官方”用法解释是:

int execve(const char * filename,char * const argv[ ],char * const envp[ ]);

execve()用来执行参数filename字符串所代表的文件路径,第二个参数是利用指针数组来传递给执行文件,并且需要以空指针(NULL)结束,最后一个参数则为传递给执行文件的新环境变量数组。

那么我们来看看下面的代码:

-------------

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 
  5 int main(int argc,char *argv[])
  6 {
  7     int i;
  8     for (i=0;i<argc;i++)
  9     {
 10         printf("arg%d:%s\n",i,argv[i]);
 11     }
 12     char **penv=__environ;
 13     while(penv&&*penv)
 14     {
 15         printf("%s\n",*penv++);
 16     }
 17     return 0;
 18 }
 19 

这个程序的作用是:输出各个命令行参数和系统的环境变量。(把此程序的编译的可执行文件test放在./Extratest/test

-----------------------------------------------------------------------------------------

那么我们再来看看下面的程序:

  1 #include <stdio.h>
  2 #include <stdlib.h>
  3 #include <unistd.h>
  4 #include <sys/wait.h>
  5 
  6 int main()
  7 {
  8     pid_t pid;
  9     int status;
 10     char *arrArg[]={"test","A","B","C",NULL};
 11     char *arrEnv[]={"env1=100","env2=yanyb",NULL};
 12     pid=vfork();
 13     if(pid<0)
 14     {
 15         printf("vfork error!");
 16         exit(1);
 17     }
 18     if(pid==0)
 19     {
 20         execve("./Extratest/test",arrArg,arrEnv);
 21     }
 22     else
 23     {
 24         if(pid!=wait(&status))
 25         {
 26             printf("wait error!");
 27             exit(1);
 28         }
 29     }
 30     return 0;
 31 }

此程序即调用上面的可执行文件,那么他是输出什么呢?

arg0:test

arg1:A
arg2:B
arg3:C
env1=100
env2=yanyb

之所以会这样,就是execve把arrArg的内容作为命令行参数传递给了可执行文件test进程。这样当调用test时,由于test程序的作用之一就是获取命令行的参数并输出(argv[i]的作用),所以原来的命令行参数是./test(所谓的命令行参数可以理解为命令的内容),现在通过传递变成了arrArg的内容;

至于环境变量,由于exceve把新的环境变量传递给了test所在的进程,所以执行完test后自然输出了新的环境变量。

-----------------------------------------------------------------------------

关于argv[]的理解,百度知道有个特别好的解释,这里分享给大家:

argv接收从命令行传来的参数,在程序里可以通过argv[i]来使用。比方你要执行的.exe文件名为test,你在命令行中输入test 2 hello world!
那么在程序里argv[0]就是hello,argv[1]就是world!上面输入的2告诉程序一共有几个命令行参数,用argc表示,就是MAIN()函数的第一个参数。
来源:知道用户 KenroJiang   的回答

<think>嗯,用户想了解Linux内核参数/proc/sys/kernel/args_max的含义和用法。这个问题涉及到Linux内核的进程管理机制,需要从多个维度解释。首先回忆这个参数的位置:/proc/sys/kernel/args_max是proc文件系统下的一个内核参数,属于sysctl调优范畴。它的核心作用是定义单个进程通过execve()系统调用执行新程序时,允许传递的最大命令行参数和环境变量总字节数。用户可能是系统管理员或开发者,遇到"Argumentlisttoolong"错误才来查询的。需要强调这个限制包括所有命令行参数和环境变量的总和,而不仅仅是参数长度。比如执行命令时,PATH、LD_LIBRARY_PATH这些环境变量都会计入总长度。关于默认值,256KB在现代系统可能偏小,特别是使用通配符匹配大量文件时。修改方法有两种:临时性修改用echo524288>/proc/sys/kernel/args_max,永久修改需要在/etc/sysctl.conf添加kernel.args_max=524288。但要注意最大不能超过MAX_ARG_STRLEN(通常2MB)。用户可能没意识到这个限制也影响环境变量。可以举例说明:假设设置PATH包含100个路径,每个路径50字节,仅PATH就占5000字节。这点需要特别提醒,因为开发者常忽略环境变量的开销。最后需要警告修改风险:过度增大可能消耗过多内核栈空间,导致内存碎片或OOM。建议用户先尝试用find-exec或xargs等规避方法。若必须修改,2MB是较安全的经验值。相关扩展问题考虑设计三个方向:如何监控参数使用量(可通过/proc/<pid>/cmdline查看)、与其他内核参数(如threads-max)的关联、以及内核源码中ARG_MAX的定义位置(linux/include/uapi/linux/binfmts.h)。这样既解决当前问题,又提供深入探索的路径。</think>`/proc/sys/kernel/args_max` 是 Linux 内核中一个重要的参数,它定义了单个进程在执行新程序时(通过 `execve()` 系列系统调用),其**命令行参数**和**环境变量**所占用的**总字节数**的最大限制。它直接对应内核常量 `MAX_ARG_STRLEN`。 ### 作用和意义 1. **限制参数和环境空间大小:** 当创建一个新进程(例如通过 shell 执行命令、程序调用 `fork` + `exec` 等)时,传递给新程序的命令行参数(`argv`)和环境变量(`environ`)的总长度(以字节计算)不能超过 `args_max` 的值。 2. **防止内核栈溢出:** 内核在执行 `execve()` 时需要在内核栈空间上临时存放这些参数和环境变量,以便设置新进程的用户空间。这个限制防止了恶意或错误程序传递超大参数列表导致内核栈溢出崩溃。 3. **保障系统稳定性:** 强制执行这个限制是内核保证自身稳定性和安全性的重要机制。 4. **错误来源:** 如果尝试执行的命令其参数和环境变量总大小超过 `args_max`,`execve()` 系统调用会失败,并设置 `errno` 为 `E2BIG` ("Argument list too long")。在 shell 中执行时,通常会看到 "Argument list too long" 的错误提示。 ### 默认值 * 在大多数现代 Linux 系统上,`args_max` 的**默认值通常是 131072 (128 KB)** 或 **262144 (256 KB)**。具体值取决于内核编译时的配置(`CONFIG_MAX_ARG_STRLEN`)。 * 这个值包括了所有命令行参数字符串、所有环境变量字符串以及指向这些字符串的指针数组(`argv[]` 和 `envp[]`)所占用的空间。注意是字符串内容本身的字节总和加上指针数组的开销。 ### 查看当前值 ```bash cat /proc/sys/kernel/args_max ``` ### 修改方法 (需要 root 权限) 修改此参数通常是为了解决 "Argument list too long" 错误,但需谨慎,因为增加它会消耗更多内核栈空间。 1. **临时修改 (重启后失效):** ```bash echo 262144 > /proc/sys/kernel/args_max # 例如设置为 256 KB (262144 bytes) ``` 2. **永久修改 (需重启或使配置生效):** * 编辑 `/etc/sysctl.conf` 文件 (或 `/etc/sysctl.d/` 目录下的 `.conf` 文件): ```bash sudo nano /etc/sysctl.conf ``` * 在文件末尾添加一行: ``` kernel.args_max = 262144 ``` * 保存文件。 * 使修改立即生效 (无需重启): ```bash sudo sysctl -p /etc/sysctl.conf ``` * 或者重启系统。 ### 重要注意事项 1. **最大值限制:** `args_max` 不能超过内核常量 `MAX_ARG_STRLEN` 的硬编码上限。这个上限通常是 **2 MB (2097152 字节)** 或 **32 页(通常 128KB)**(具体取决于架构和内核版本,由 `include/uapi/linux/binfmts.h` 中的 `#define MAX_ARG_STRLEN` 决定)。尝试设置超过此硬上限的值是无效的,内核会静默地将其设置为上限值。 2. **内核栈消耗:** 增加 `args_max` 意味着内核在执行 `execve()` 时需要在内核栈上分配更多空间来暂存参数和环境。虽然现代内核采用了一些技术(如复制到临时页)来缓解,但过度增大仍可能带来风险(尤其是在内存紧张或嵌套调用很深时)。 3. **替代方案优先:** 在遇到 "Argument list too long" 错误时,**优先考虑优化命令本身**通常比增大 `args_max` 更安全、更合理: * 使用 `find -exec` 或 `xargs` 处理大量文件。 * 将参数写入文件,让程序从文件中读取。 * 精简环境变量。 * 使用通配符 (`*`) 时,确保匹配的文件数量不会导致参数列表过长(shell 会展开通配符)。 4. **环境变量计入:** 记住,环境变量 (`env`) 的大小也计入 `args_max` 限制。一个臃肿的环境变量列表同样会触发 `E2BIG` 错误。 ### 总结 `/proc/sys/kernel/args_max` 定义了单个进程在启动时能接收的最大命令行参数和环境变量总大小(字节数)。它默认通常在 128KB 或 256KB,最大硬限制通常为 2MB。其主要作用是防止超大参数列表导致内核栈溢出,保障系统稳定。虽然可以临时或永久修改其值以解决 "Argument list too long" 错误,但应优先考虑优化命令结构或使用替代方案(`xargs`, 文件输入),修改内核参数需谨慎评估对内核栈的影响。 [^1]: 内核参数是众多且多样的,值得深入了解。参见官方文档:https://www.kernel.org/doc/html/latest/admin-guide/kernel-parameters.html。 [^2]: Linux 内核设计与实现涉及动态加载模块、对称多处理、抢占式内核、统一处理内核线程、面向对象设备模型等特性,摒弃了过时的 Unix 设计理念。 [^3]: 内置于内核的模块参数需要在 kernel 命令行中指定。modprobe 在加载模块时会检查 kernel 命令行 (/proc/cmdline) 并收集模块参数,因此 kernel 命令行也可用于可加载模块。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值