问题背景
execvp: /bin/sh: Argument list too long问题出现的两种情况:
- 1、make的时候,如编译Linux内核、驱动、Android版本等较长-I、-D选项的情况;
- 2、shell操作,涉及较多文件的情况,如删除大量文件时,直接用rm;
问题原因
1、错误来源于sysdeps/gnu/errlist.c文件中:
[ERR_REMAP (E2BIG)] = N_("Argument list too long"),
可据此找到对应Linux内核中exec.c中返回E2BIG的地方,实际和ARG_MAX有很大关系。
2、参考APUE,ARG_MAX的值在运行时间不变的值,但值可能不确定。
ARG_MAX的值实际上和下面参数有关系:
- MAX_ARG_STRLEN #单个字符串的最大大小 - MAX_ARG_STRINGS #参数个数的限制 - MAX_ARG_PAGES #分配给参数的最大页数 - stack size #堆栈空间 - ARG_MAX in limits.h #参数的最大长度
实际上,不同内核的版本也有区别。
几个命令执行情况的例子:
[qxhgd@localhost]getconf ARG_MAX 2897152 [qxhgd@localhost]ulimit -s 8192 [qxhgd@localhost]xargs --show-limits Your environment variables take up 4222 bytes POSIX upper limit on argument length (this system): 2090882 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2086660 Size of command buffer we are actually using: 131072
问题解决
几种思路
- 修改主机环境:
- 调整shell命令或makefile本身;
修改主机环境
据说,Linux内核可通过修改下面参数来规避,具体没做实验。
/* * MAX_ARG_PAGES defines the number of pages allocated for arguments * and envelope for the new program. 32 should suffice, this gives * a maximum env+arg of 128kB w/4KB pages! */ #define MAX_ARG_PAGES 32
其他几个参数也可根据需要调整。
shell操作场景
- 以rm为例,一般配合xargs利用管道来解决:
find . -name “" | xargs rm -rf "” 就行
- 也可以通过shell来执行:
#!/bin/bash # 设定需要删除的文件夹 RM_DIR='/testdir/to-del-all' cd $RM_DIR for I in `ls` do rm -f $I
make场景
1、对于-I路径
- 去除冗余的-I路径
如某模块在增加-I路径的时候,没有确认是否真的需要,只是参考其他模块直接copy的。
- 将路径包含设法缩短
如有的路径里有类似这种A/xx/yy…/…/的,就可以优化一下;
另外,也可以用软链接来缩短路径;
- 将需要的头文件整合到一个目录中。
2、对于-D选项
- 可以将相关-D选项生成.h文件,直接include相关.h文件。
命令汇总
getconf ARG_MAX #查看系统配置参数ARG_MAX sys/limits.h #头文件 xargs --show-limits #xargs查看各种参数的长度 MAX_ARG_STRLEN #include/linux/binfmts.h文件 cat /proc/$$/environ | wc -c #查看环境变量长度; ulimit -s #查看或修改线程默认栈空间 echo $(( $(getconf PAGE_SIZE)*32 )) ##查看PAGE_SIZE
参考资料
- APUE