字符串可以传递到system()
多长时间?
我知道POSIX的最小值是4096,但我想知道可以使用的实际尺寸。是否在任何标头中为此定义了任何宏,类似于FILENAME_MAX
?
char cmd[SOME_MACRO];
...
system(cmd);
答案 0 :(得分:9)
system
执行程序是带有参数"sh","-c", YourAgumentToSystem, (char*)0
(guaranteed by POSIX)的shell,因此
最大长度(不计算'\0'
终止符)为ARG_MAX -1 -3 -3 - size_of_your_environment
。
ARG_MAX
在limits.h中定义为
“ exec函数的最大参数长度,包括 环境数据。”
如果limits.h
未定义ARG_MAX
,则您should be able to call
sysconf(_SC_ARG_MAX)
获取运行时限制。
execve的linux联机帮助页(由系统调用)提供了更多信息:
在内核2.6.23之前的Linux上,用于存储内存的内存 环境和参数字符串限制为32页(由 内核常量MAX_ARG_PAGES)。在页面大小为4 kB的体系结构上 大小,则最大大小为128 kB。
在内核2.6.23和更高版本上,大多数体系结构都支持大小限制 从软RLIMIT_STACK资源限制派生(请参见getrlimit(2)) 在execve()调用时生效。 (与 不排除任何内存管理单元:它们保持以下限制: 在内核2.6.23之前有效。)此更改允许程序执行以下操作: 具有更大的参数和/或环境列表。对于这些 架构,总大小限制为允许堆栈的1/4 尺寸。 (强加1/4限制可确保新程序始终具有 从Linux 2.6.25开始,内核将底数设置为32 页面上有此大小限制,因此即使将RLIMIT_STACK设置为非常大 低,保证应用程序至少具有尽可能多的参数和 Linux 2.6.23和更早版本提供的环境空间。 (这个 Linux 2.6.23和2.6.24中未提供保证。)此外, 每个字符串的限制为32页(内核常量MAX_ARG_STRLEN), 并且最大字符串数为0x7FFFFFFF。
要测量环境的大小,可以运行:
extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;
(正如Zan Lynx在评论中指出的那样,这可以加快速度(根据我的测量结果,大约为20倍-对于测量时具有100串6KB环境,从1600ns到80ns)
如果您假设char*
中的environ
指针指向一个连续的缓冲区,则它们在程序启动后会执行,但是会调用setenv
,putenv
或{{1} }通常会打破这一点:
unsetenv
在任何情况下,如果您希望很快使用fork + exec(/ system),那么以健壮性为代价进行的加速就没什么大不了的,因为在Linux上,fork + exec通常花费至少1-2ms左右在现代机器上。)
答案 1 :(得分:4)
此限制与系统高度相关。它甚至可能取决于将要使用的命令外壳。您应该测试system()
的返回值以查看系统调用是否成功:-1
表示失败,errno
应该给您更多信息。应该为任何适当的C字符串定义行为。
POSIX文档证明system(command)
等同于:
execl(<shell path>, "sh", "-c", command, (char *)0);
还有ARG_MAX
中定义的<limits.h>
文档,作为exec
的参数和环境变量的组合长度的限制。
但是请注意,command
可能包含通配符和/或其他扩展名可能超出其他限制的shell字。始终检查返回值是否失败。
答案 2 :(得分:3)
man 3系统
给我们
说明
system()库函数使用fork(2)创建一个子进程,该子进程执行command中指定的shell命令 使用execl(3)如下:
execl("/bin/sh", "sh", "-c", command, (char *) 0); system() returns after the command has been completed.
因此system()是
execl()
的包装器
在同一页面上,我们还看到此调用符合某些标准。
符合
POSIX.1-2001,POSIX.1-2008,C89,C99。
查找 POSIX.1-2008 会生成以下在线参考
https://pubs.opengroup.org/onlinepubs/9699919799/
我们可以在哪里搜索有关execl
函数的信息,系统会将我们带到该函数
https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
其中提供以下内容
新进程的组合参数和环境列表可用的字节数为{ARG_MAX}。在实现中定义是否在此总数中包括空终止符,指针和/或任何对齐字节。
最后...
错误
在以下情况下,exec函数将失败:
[E2BIG]新过程映像的参数使用的字节数 列表和环境列表大于系统施加的限制 {ARG_MAX}个字节。
因此,此处要执行的最后检查是实际的exec实现,而不是依赖于标准,以防万一实现偏离标准。
因此,man 3 execl
报告返回的错误与execve(2)
记录的错误相同,而man 2 execvw
报告以下内容:
错误
E2BIG环境(envp)和参数列表(argv)中的字节总数太大。
不如POSIX标准精确吗?最好检查代码或查看(现在)已接受的答案:)