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

system() function string length limit

一个字符串可以传递给system()多长时间?

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

char cmd[SOME_MACRO];

...
system(cmd);

该限制高度依赖于系统。它甚至可能取决于将要使用的命令 shell。您应该测试 system() 的 return 值以查看系统调用是否成功:-1 表示失败,errno 应该会为您提供更多信息。应该为任何适当的 C 字符串定义行为。

POSIX 记录 system(command) 等同于:

execl(<shell path>, "sh", "-c", command, (char *)0);

还有文档 ARG_MAX<limits.h> 中定义为 exec 的参数和环境变量的组合长度的限制。

但是请注意,command 可能包含通配符 and/or 其他 shell 扩展可能超过其他限制的单词。始终检查 return 值是否失败。

system exec's a shell with arguments "sh","-c", YourAgumentToSystem, (char*)0 (guaranteed by POSIX), 所以 最大长度(不包括 '[=14=]' 终止符)是 ARG_MAX -1 -3 -3 - size_of_your_environment.

ARG_MAXlimits.h 中定义为

"Maximum length of argument to the exec functions including environment data."

如果limits.h,没有定义ARG_MAX,你should be able to call sysconf(_SC_ARG_MAX) 获得 运行 时间限制。

execve(由系统调用)的 linux 联机帮助页提供了更多信息:

On Linux prior to kernel 2.6.23, the memory used to store the environment and argument strings was limited to 32 pages (defined by the kernel constant MAX_ARG_PAGES). On architectures with a 4-kB page size, this yields a maximum size of 128 kB.

On kernel 2.6.23 and later, most architectures support a size limit derived from the soft RLIMIT_STACK resource limit (see getrlimit(2)) that is in force at the time of the execve() call. (Architectures with no memory management unit are excepted: they maintain the limit that was in effect before kernel 2.6.23.) This change allows programs to have a much larger argument and/or environment list. For these architectures, the total size is limited to 1/4 of the allowed stack size. (Imposing the 1/4-limit ensures that the new program always has some stack space.) Since Linux 2.6.25, the kernel places a floor of 32 pages on this size limit, so that, even when RLIMIT_STACK is set very low, applications are guaranteed to have at least as much argument and environment space as was provided by Linux 2.6.23 and earlier. (This guarantee was not provided in Linux 2.6.23 and 2.6.24.) Additionally, the limit per string is 32 pages (the kernel constant MAX_ARG_STRLEN), and the maximum number of strings is 0x7FFFFFFF.

要测量环境的大小,您可以 运行:

extern char **environ;
size_t envsz = 0; for(char **e=environ; *e; e++) envsz += strlen(*e)+1;

(正如 Zan Lynx 在评论中所指出的那样,这可以加快(根据我的测量结果,cca 20 倍——对于我测量时的 100 串 6KB 环境,从 1600ns 到 80ns) 如果您假设 environ 中的 char* 指针指向一个连续的缓冲区,它们在程序启动后执行,但调用 setenvputenvunsetenv 通常打破这个:

extern char **environ;
char **e; for(e=environ; *e; e++) {}
size_t envsz =  ($_sz)(e[-1]+strlen(e[-1])+1 - *environ);

在任何情况下,如果您希望很快使用 fork+exec (/system),那么以健壮性为代价的加速应该无关紧要,因为 fork+exec 通常至少花费 1-2 毫秒左右Linux 在现代机器上。)

man 3 system

给我们

DESCRIPTION

The system() library function uses fork(2) to create a child process that executes the shell command specified in command using execl(3) as follows:

       execl("/bin/sh", "sh", "-c", command, (char *) 0);

   system() returns after the command has been completed.

so system() is a wrapper for execl()

从同一页面我们也看到这个调用符合一些标准。

CONFORMING TO

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

提供以下内容

The number of bytes available for the new process' combined argument and environment lists is {ARG_MAX}. It is implementation-defined whether null terminators, pointers, and/or any alignment bytes are included in this total.

最后...

ERRORS

The exec functions shall fail if:

[E2BIG] The number of bytes used by the new process image's argument list and environment list is greater than the system-imposed limit of {ARG_MAX} bytes.

所以这里要执行的最后检查是实际的 exec 实现,而不是依赖标准以防万一实现偏离标准。

因此,man 3 execl 报告返回的错误与 execve(2) 的记录相同,man 2 execvw 报告如下:

ERRORS

E2BIG The total number of bytes in the environment (envp) and argument list (argv) is too large.

不如 POSIX 标准精确?最好检查代码或查看(现在)接受的答案:)