系统配置“变量”ARG_MAX 的 Linux 实现是否与其他系统变量不同,是否符合 POSIX?

5 history limit posix

在 shell 中,正如本问答在扩展上下文中所解释的,根据系统,命令参数的最大长度最初受内核设置的约束。最大值在运行时使用getconf命令显示(另请参见IEEE Std 1003.1, 2013 Edition):

# getconf ARG_MAX
2097152
vs. value found in limits.h on my setup:
#define ARG_MAX       131072    /* # bytes of args + environ for exec() */
Run Code Online (Sandbox Code Playgroud)

的确:

sysconf() 调用提供一个值,该值对应于程序编译或执行时的条件,具体取决于实现;对 getconf 的 system() 调用总是在程序执行时提供与条件相对应的值。

联机帮助页参考了 POSIX,从暗指POSIX 程序员手册的序言到描述本身:

应确定每个配置变量的值,就好像它是通过调用定义为可用的函数获得的,POSIX.1-2008 的本卷或 POSIX.1-2008 的系统接口卷(参见操作数部分)。该值应反映当前操作环境中的条件。

可以查询的基本变量出现在sysconf函数规范表中,limits.h头文件中有关于这些值的更多信息:

{ARG_MAX}
    Maximum length of argument to the exec functions including environment data.
    Minimum Acceptable Value: {_POSIX_ARG_MAX}
...(nb you cannot be POSIX compliant under a certain value...)
{_POSIX_ARG_MAX}
    Maximum length of argument to the exec functions including environment data.
    Value: 4 096
Run Code Online (Sandbox Code Playgroud)

xargs --show-limits命令确认了其中的一些内容:

Your environment variables take up 3134 bytes
POSIX upper limit on argument length (this system): 2091970
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2088836
Size of command buffer we are actually using: 131072
Run Code Online (Sandbox Code Playgroud)

sysconf最初设计用于查找 PATH 变量的系统值,然后扩展到其他变量。现在,Open Group文档探讨了拥有这样一个框架的基本原理,其中应用程序可以在运行时轮询系统变量,以及有关基线的相关实际考虑...:

(...) 如果仅限于标题中最严格的值,则此类应用程序必须准备好接受由最小的微型计算机提供的最有限的环境。尽管这完全是可移植的,但人们一致认为它们应该能够利用大型系统提供的设施,而不受与源和对象分发相关的限制。

在讨论此功能期间,有人指出,应用程序几乎总是可以通过适当地测试各种函数本身来辨别运行时可能是什么值。并且,在任何情况下,它始终可以编写为充分处理来自各种函数的错误返回。最后,人们认为这给应用程序开发人员带来了不合理的复杂性和复杂性。

...以及这种设置的缺点,因为它与某些文件变量有关fpathconf

pathconf() 函数是在 sysconf() 函数之后提出的,当时意识到某些可配置值可能会因文件系统、目录或设备边界而异。

例如,{NAME_MAX} 在 System V 和基于 BSD 的文件系统之间频繁变化;System V 最多使用 14 个,BSD 255。在提供两种类型文件系统的实现中,应用程序将被迫将所有路径名组件限制为 14 个字节,因为这将是在此类系统中指定的值。

因此,目的是减轻开发人员对基线的一些负担,同时也承认文件系统的多样性,并且通常允许对平台的不同变体进行一些定制。硬件、Unix和相关标准(C 和 POSIX)的演变在这里发挥了作用。

问题:

  • 该命令getconf没有一个“列表”选项,然后setprintenvexport不显示这些变量。是否有列出它们值的命令?
  • 为什么像这样的设施fpathconf看起来是为了引入更多的灵活性,但仅适用于 PATH 和文件相关的系统变量?仅仅是因为当时 getconf 只是关于 PATH 吗?
  • 当前的 Linux实现是什么,是否符合 POSIX?在链接的 Q 中,参考 ARG_MAX 的答案随堆栈大小而变化(“在 Linux 3.11 上......堆栈大小限制的四分之一,如果小于 512kiB,则为 128kiB”):
    • 这样做的理由是什么?
    • 这个选择(堆栈大小的 1/4)是 Linux 特定的实现还是只是基本实现之上的一个特性,或者历史上的 UNIX 实现是否总是基本上产生堆栈大小的 1/4?
    • 除了 ARG_MAX 之外,还有许多其他变量是堆栈大小或类似资源的函数,还是该变量的重要性需要特殊处理?
    • 实际上,是否提供了符合 POSIX 的 Linux 系统/解决方案,并且有堆栈大小限制的配置,例如,如果某些应用程序随硬件扩展,则允许某些应用程序超出基本的最大规格,或者是一种直接定制limits.h和编译的做法针对特定需求?
    • 使用类似 ARG_MAX 之类的东西limits.h与在运行时使用ulimit -s命令之类的东西更改变量与让内核直接管理它之间有什么区别?特别是limits.h由于内核更改,我在 Linux 上过时的变量的(低)值是否已被取代?
  • 命令行应该有特定于 shell 的长度限制,这些限制与扩展和 ARG_MAX 无关;他们在bash什么地方?

Gil*_*il' 3

没有标准方法来检索系统支持的配置变量列表。如果您针对给定的 POSIX 版本进行编程,则该版本的 POSIX 规范中的列表就是您的参考列表。在 Linux 上,getconf -a列出所有可用变量。

fpathconf不是特定于 PATH 的。它涉及与文件相关的变量,这些变量可能因文件而异。

在 Linux 上,取决于ARG_MAX堆栈大小的基本原理是参数最终位于堆栈上,因此最好有足够的空间容纳它们以及必须容纳的其他所有内容。大多数其他实现(包括旧版本的 Linux)都有固定的大小。

大多数限制与资源可用性相关,不同的资源取决于限制。OPEN_MAX例如,如果系统没有可用于文件相关数据的内存,则进程可能无法打开文件,即使打开的文件数少于文件数。

Linux 在这一点上默认是兼容 POSIX 的,所以我不知道你的意思。

如果您将ulimit -s堆栈大小限制为小于ARG_MAX,则系统将不再合规。POSIX 系统通常可以通过多种方式变得不合规,包括PATH=/nowhere(使所有标准实用程序不可用)或rm -rf /

ARG_MAXin的值limits.h提供了应用程序可以依赖的最小值。execve即使参数超过该大小,符合 POSIX 的系统也允许 let成功。相关的保证ARG_MAX是,如果参数适合该大小,则execve不会因 原因而失败E2BIG