Fundo:
A sobrecarga de chamadas do sistema é muito maior que a sobrecarga de chamadas de função (as estimativas variam de 20 a 100x) principalmente devido à alternância de contexto do espaço do usuário para o espaço do kernel e vice-versa. É comum que as funções embutidas reduzam as despesas gerais das chamadas de função e as chamadas de função são muito mais baratas que os syscalls. É lógico que os desenvolvedores desejam evitar parte da sobrecarga de chamadas do sistema cuidando da maior operação possível no kernel em um syscall.
Problema:
Isso criou um grande número de chamadas (supérfluos?) Do sistema, como sendmmsg () , recvmmsg () , bem como o chdir, aberto, lseek e / ou combinações link simbólico como: openat
, mkdirat
, mknodat
, fchownat
, futimesat
, newfstatat
, unlinkat
, fchdir
, ftruncate
, fchmod
, renameat
, linkat
, symlinkat
, readlinkat
, fchmodat
, faccessat
, lsetxattr
, fsetxattr
, execveat
, lgetxattr
, llistxattr
, lremovexattr
, fremovexattr
, flistxattr
, fgetxattr
,pread
, pwrite
etc ...
Agora, o Linux adicionou o copy_file_range()
que aparentemente combina lseek de leitura e syscalls de gravação. É apenas uma questão de tempo até que isso se torne fcopy_file_range (), lcopy_file_range (), copy_file_rangeat (), fcopy_file_rangeat () e lcopy_file_rangeat () ... mas como existem 2 arquivos envolvidos em vez de mais X chamadas, ele pode se tornar X ^ 2 Mais. OK, Linus e os vários desenvolvedores do BSD não deixaram isso ir tão longe, mas o que quero dizer é que, se houvesse um syscall em lote, todos (a maioria?) Deles poderiam ser implementados no espaço do usuário e reduzir a complexidade do kernel sem adicionar muito se houver alguma sobrecarga no lado da libc.
Muitas soluções complexas foram propostas que incluem algum thread syscall especial de formulário para syscalls sem bloqueio para syscalls de processos em lote; no entanto, esses métodos adicionam complexidade significativa ao espaço do kernel e do usuário da mesma maneira que libxcb vs. libX11 (as chamadas assíncronas exigem muito mais configuração)
Solução?:
Um syscall de lote genérico. Isso aliviaria o maior custo (comutadores de modo múltiplo) sem as complexidades associadas à existência de encadeamento especializado do kernel (embora essa funcionalidade possa ser adicionada posteriormente).
Basicamente, já existe uma boa base para um protótipo no syscall socketcall (). Apenas estenda a partir de uma matriz de argumentos para obter uma matriz de retornos, ponteiro para matrizes de argumentos (que inclui o número syscall), o número de syscalls e um argumento flags ... algo como:
batch(void *returns, void *args, long ncalls, long flags);
Uma diferença importante seria que os argumentos provavelmente todos necessidade de ser ponteiros para simplicidade para que os resultados de syscalls anteriores poderia ser usado por syscalls subsequentes (por exemplo, o descritor de arquivo de open()
para uso em read()
/ write()
)
Algumas vantagens possíveis:
- menos espaço do usuário -> espaço do kernel -> comutação do espaço do usuário
- possível alternador do compilador -fcombine-syscalls para tentar agrupar automaticamente
- sinalizador opcional para operação assíncrona (retorne fd para assistir imediatamente)
- capacidade de implementar futuras funções syscall combinadas no espaço do usuário
Questão:
É possível implementar uma syscall em lote?
- Estou perdendo algumas dicas óbvias?
- Estou superestimando os benefícios?
Vale a pena me preocupar em implementar uma syscall em lotes (não trabalho na Intel, Google ou Redhat)?
- Eu já corrigi meu próprio kernel antes, mas tenho medo de lidar com o LKML.
- A história mostrou que, mesmo que algo seja amplamente útil para usuários "normais" (usuários finais não corporativos sem acesso de gravação git), ele nunca poderá ser aceito a montante (unionfs, aufs, cryptodev, tuxonice, etc ...)
Referências:
batch
syscalls embatch
syscalls, você pode criar uma árvore chamada arbitrariamente profunda de syscalls arbitrárias. Basicamente, você pode colocar todo o aplicativo em um único syscall.