Escrever para um soquete é uma limitação arbitrária do sendfile () syscall?
-
18-09-2019 - |
Pergunta
Prelúdio
sendfile()
é um syscall extremamente útil por dois motivos:
Primeiro, é menos código do que um read()
/write()
(ou recv()
/send()
Se você preferir esse loop de jive).
Segundo, é mais rápido (Menos syscalls, a implementação pode copiar entre dispositivos sem buffer, etc ...) do que os métodos acima mencionados.
Menos código. Mais eficiente. Incrível.
No Unix, tudo é (principalmente) um arquivo. Este é o território feio da colisão da teoria platônica e da prática do mundo real. Entendo que os soquetes são fundamentalmente diferentes dos arquivos residentes em algum dispositivo. Eu não cavei as fontes de Linux/*bsd/darwin/o que quer que os implementos do sistema operacional sendfile()
Para saber por que esse syscall específico está restrito à escrita aos soquetes (especificamente, com soquetes de streaming).
Eu só quero saber...
Pergunta
O que é limitador sendfile()
De permitir que o descritor de arquivo de destino seja algo além de um soquete (como um arquivo de disco ou um tubo)?
Solução
Fundamentalmente, a única coisa que limita é que "ninguém escreveu o código ainda".
No entanto, concluo que a razão pela qual ninguém escreveu o código para os dois casos que você menciona é que ambos exigiriam que os dados fossem copiados, o que remove grande parte da vantagem de usar sendfile
em primeiro lugar.
Para um arquivo a arquivo
sendfile
, você precisaria de uma cópia porque, caso contrário, a mesma página teria que estar no Pagecache como uma página limpa no arquivo de origem e uma página suja no arquivo de destino. Não acho que o Pagecache tenha sido construído para lidar com esse caso no momento (embora, é claro, isso possa ser alterado se houvesse motivação suficiente).Para um arquivo a tubo
sendfile
, você precisa de uma cópia, independentemente disso, porque o processo de destino precisa obter uma cópia privada e escrita dos dados. Enfim, para a maioria dos usos deste caso, já temosmmap
.
Outras dicas
Parece que me lembro que foi uma limitação introduzida no Linux 2.6 (2.4, não tinha a limitação).
Como 2.6.17 Linux possui a chamada do sistema Splice (), que é semelhante; Mais flexível, mas um pouco menos eficiente. Linus falou sobre reimplementar o SendFile em termos de Splice (). Ver http://kerneltrap.org/node/6505