Em sistemas Unix, os nomes de caminhos geralmente não têm limitação de comprimento (bem, 4096 caracteres no Linux)... exceto para caminhos de arquivos de soquete que são limitados acerca de 100 caracteres(107 caracteres emLinux).
- Primeira pergunta:por que uma limitação tão baixa?
Eu verifiquei que parece possível contornar essa limitação alterando o diretório de trabalho atual e criando em vários diretórios vários arquivos de soquete, todos usando o mesmo caminho ./myfile.sock
: os aplicativos clientes parecem se conectar corretamente aos processos esperados do servidor, embora lsof
mostrem tudo deles ouvindo no mesmo caminho do arquivo de soquete.
- Esta solução alternativa é confiável ou tive sorte?
- Este comportamento é específico do Linux ou esta solução alternativa também pode ser aplicável a outros Unixes?
Responder1
Compatibilidade com outras plataformas ou compatibilidade com coisas mais antigas para evitar sobrecargas ao usar snprintf()
e strncpy()
.
Michael Kerrisk explica emlivro delenopágina 1165- Capítulo 57, Sockets: domínio Unix:
SUSv3 não especifica o tamanho do campo sun_path. As primeiras implementações do BSD usavam 108 e 104 bytes, e uma implementação contemporânea (HP-UX 11) usava 92 bytes. Aplicativos portáteis devem codificar para esse valor mais baixo e usar snprintf() ou strncpy() para evitar saturação de buffer ao escrever neste campo.
Os caras do Docker até zombaram disso, porque alguns soquetes tinham 110 caracteres:
É por isso que o LINUX usa um soquete de 108 caracteres. Isso poderia ser mudado? Claro. E esta é a razão pela qual esta limitação foi criada em primeiro lugar em sistemas operacionais mais antigos:
Citando a resposta:
Era para corresponder ao espaço disponível em uma estrutura de dados do kernel útil.
Citando "O Projeto e Implementação do Sistema Operacional 4.4BSD" por McKusick et. al. (página 369):
Os recursos de gerenciamento de memória giram em torno de uma estrutura de dados chamada mbuf. Mbufs, ou buffers de memória, têm 128 bytes de comprimento, sendo 100 ou 108 bytes desse espaço reservado para armazenamento de dados.
Outros sistemas operacionais (soquetes de domínio unix):
- OpenBSD: 104 caracteres
- FreeBSD: 104 caracteres
- Mac OS X 10.9: 104 caracteres
Responder2
Quanto ao porquê, nwildner já escreveu umexcelente resposta.
Aqui vou me concentrar apenas em como e no uso do caminho relativo.
Internamente, embora o arquivo de soquete também possa ser pesquisado por nome (eu acho), eles geralmente são pesquisados por inode. No Linux, esta consulta é garantida pela função unix_find_socket_byinode()
definida emnet/unix/af_unix.c.
Isso pode ser facilmente verificado da seguinte forma:
- Crie dois diretóriosA/eB/.
- Em cada diretório, faça um processo escutar arquivos de soquete com o mesmo nome. Com
socat
você usaria um comando como:
$ socat UNIX-LISTEN:./my.sock -
- Agora troque os arquivos de soquete movendoA/minha.sockparaB/e vice versa.
- De agora em diante, se o aplicativo cliente se conectar aoA/minha.sockele entrará em contato com o servidorB, e se ele se conectar aB/minha.meiaele entrará em contato com o servidorA(observe que quando a comunicação termina, o processo do servidor pode excluir legitimamente o que pensa ser seu próprio arquivo de soquete).
Eu verifiquei esse comportamento em alguns sistemas Unix (Linux Debian, FreeBSD e OpenIndiana para obter alguma diversidade), então esse comportamento parece ser pelo menos generalizado, se não padrão.
Caminhos absolutos são geralmente usados como uma convenção entre os processos cliente e servidor, pois de outra forma o processo cliente pode não saber como estabelecer a comunicação inicial com o servidor.
No entanto, se esta comunicação inicial não for um problema, parece seguro usar caminhos relativos para a criação de arquivos de soquete, permitindo evitar problemas de comprimento de caminho quando a localização do arquivo de soquete não é controlada diretamente pelo processo do servidor.