system()函数字符串的长度限制

时间:2019-04-13 15:08:40

标签: c linux posix

字符串可以传递到system()多长时间?

我知道POSIX的最小值是4096,但我想知道可以使用的实际尺寸。是否在任何标头中为此定义了任何宏,类似于FILENAME_MAX

char cmd[SOME_MACRO];

...
system(cmd);

3 个答案:

答案 0 :(得分:9)

system执行程序是带有参数"sh","-c", YourAgumentToSystem, (char*)0guaranteed by POSIX)的shell,因此 最大长度(不计算'\0'终止符)为ARG_MAX -1 -3 -3 - size_of_your_environment

ARG_MAXlimits.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指针指向一个连续的缓冲区,则它们在程序启动后会执行,但是会调用setenvputenv或{{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标准精确吗?最好检查代码或查看(现在)已接受的答案:)