No shell, conforme explicado nesta Q & A no contexto da expansão, dependendo do sistema, o comprimento máximo do argumento de um comando é inicialmente restringido pela configuração do kernel. O valor máximo é revelado em tempo de execução usando o comando getconf
(veja também IEEE Std 1003.1, edição 2013 ):
# getconf ARG_MAX
2097152
vs. value found in limits.h on my setup:
#define ARG_MAX 131072 /* # bytes of args + environ for exec() */
De fato:
The sysconf() call supplies a value that corresponds to the conditions
when the program was either compiled or executed, depending on the
implementation; the system() call to getconf always supplies a value
corresponding to conditions when the program is executed.
As páginas de manual fazem referência ao POSIX, desde o prólogo que alude ao manual do Programador POSIX , à descrição :
The value of each configuration variable shall be determined as if it
were obtained by calling the function from which it is defined to be
available by this volume of POSIX.1-2008 or by the System Interfaces
volume of POSIX.1-2008 (see the OPERANDS section). The value shall
reflect conditions in the current operating environment.
As variáveis básicas que podem ser consultadas aparecem na tabela para a especificação da função sysconf
e há mais informações sobre os valores no limits.h
documentação do cabeçalho:
{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
O comando xargs --show-limits
confirma um pouco disso:
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
sysconf
foi projetado inicialmente para encontrar o valor do sistema para a variável PATH e, em seguida, foi estendido para outras variáveis. Agora, a documentação do Open Group explora as razões para ter tal framework onde as aplicações podem pesquisar variáveis de sistema em tempo de execução, e as considerações práticas relacionadas sobre a linha de base ...:
(...) If limited to the most restrictive values in the headers, such
applications would have to be prepared to accept the most limited
environments offered by the smallest microcomputers. Although this is
entirely portable, there was a consensus that they should be able to
take advantage of the facilities offered by large systems, without the
restrictions associated with source and object distributions.
During the discussions of this feature, it was pointed out that it is
almost always possible for an application to discern what a value
might be at runtime by suitably testing the various functions
themselves. And, in any event, it could always be written to
adequately deal with error returns from the various functions. In the
end, it was felt that this imposed an unreasonable level of
complication and sophistication on the application developer.
... bem como as deficiências de tal configuração no que se refere a algumas variáveis de arquivo com fpathconf
:
The pathconf() function was proposed immediately after the sysconf()
function when it was realized that some configurable values may differ
across file system, directory, or device boundaries.
For example, {NAME_MAX} frequently changes between System V and
BSD-based file systems; System V uses a maximum of 14, BSD 255. On an
implementation that provides both types of file systems, an
application would be forced to limit all pathname components to 14
bytes, as this would be the value specified in on such a
system.
Portanto, a intenção era aliviar os desenvolvedores de alguns obstáculos para a linha de base e, ao mesmo tempo, reconhecer a variedade nos sistemas de arquivos e, geralmente, permitir a personalização em diferentes variantes da plataforma. A evolução do hardware, Unix e padrões relacionados (C e POSIX) tem um papel aqui.
Perguntas:
- O comando
getconf
não tem uma opção "list" e set
, printenv
ou export
não mostram essas variáveis. Existe um comando que lista seu valor?
- Por que instalações como
fpathconf
foram criadas para introduzir mais flexibilidade, mas apenas para variáveis de sistema relacionadas a arquivos e PATH? É só porque naquele momento o getconf era apenas sobre o PATH?
- Qual é a implementação atual do Linux e é compatível com POSIX? No Q vinculado, há referência em as respostas para ARG_MAX variando com o tamanho da pilha ("no Linux 3.11 ... um quarto do limite definido no tamanho da pilha, ou 128kiB se for menor que 512kiB"):
- Qual é a razão para isso?
- Essa escolha (1/4 do tamanho da pilha) é uma implementação específica do Linux ou apenas um recurso na implementação básica ou a implementação histórica do UNIX sempre rendeu basicamente 1/4 do tamanho da pilha?
- Muitas outras variáveis além do ARG_MAX são uma função do tamanho stack ou recursos semelhantes ou a importância dessa variável garante um tratamento especial?
- Praticamente, alguém entrega um sistema / solução Linux compatível com POSIX e há uma configuração do limite de tamanho de pilha, por exemplo, para permitir que algum aplicativo ultrapasse as especificações máximas básicas se for escalonado com o hardware ou se for uma prática customizar diretamente
limits.h
e compila para necessidades específicas?
- Qual é a diferença para algo como ARG_MAX entre usar
limits.h
vs. alterar a variável em tempo de execução com algo como ulimit -s
comando vs. tendo o kernel gerenciado diretamente? Em particular, o valor (baixo) dessa variável no meu limits.h
obsoleto no Linux por causa das alterações do kernel, ou seja, foi substituído?
- A linha de comando supostamente tem restrições de comprimento específicas do shell que não estão relacionadas à expansão e ao ARG_MAX; o que são em
bash
?