Por que os números de chamada do sistema Linux em x86 e x86_64 são diferentes?

35

Eu sei que a interface de chamada do sistema é implementada em um nível baixo e, portanto, depende da arquitetura / plataforma, não do código "genérico".

No entanto, não consigo ver claramente o motivo pelo qual as chamadas do sistema nos kernels x86 de 32 bits do Linux têm números que não são mantidos iguais na arquitetura semelhante x86_64 do Linux de 64 bits? Qual é a motivação / razão por trás dessa decisão?

Meu primeiro palpite foi que um motivo de segundo plano foi manter aplicativos de 32 bits executáveis ​​em um sistema x86_64, para que, através de um deslocamento razoável para o número de chamada do sistema, o sistema saiba que o espaço do usuário é de 32 ou 64 bits. respectivamente. No entanto, este não é o caso. Pelo menos parece-me que read () sendo o número de chamada do sistema 0 em x86_64 não pode ser alinhado com esse pensamento.

Outro palpite é que a alteração dos números de chamada do sistema pode ter um histórico de segurança / proteção, algo que não fui capaz de confirmar.

Ignorando os desafios da implementação das partes de código dependentes da arquitetura, ainda me pergunto como alterar os números de chamada do sistema , quando parece não haver necessidade (pois mesmo um registro de 16 bits armazenaria muito mais que os atualmente ~ 346 números para representar todos os chamadas), ajudaria a conseguir qualquer coisa, além de quebrar a compatibilidade (embora o uso das chamadas do sistema por meio de uma biblioteca, a libc a atenue).

humanidade e paz
fonte
3
Eu acho que você está fazendo a pergunta errada. A pergunta correta é por que mantê-los iguais: Compatibilidade de respostas. Portanto, se x86 e x86_64 são incompatíveis, não há forças para impedi-los de mudar. Agora todas as forças dos últimos 20 anos que desejavam mudar, dominarão (temos a chance de mudá-las). [Nota este é apenas opinião e não com base na mente interior dos designers do novo sistema.]
ctrl-alt-Delor

Respostas:

34

Quanto ao raciocínio por trás da numeração específica, que não corresponde a nenhuma outra arquitetura [exceto "x32", que na verdade é apenas parte da arquitetura x86_64]: Nos primórdios do suporte ao x86_64 no kernel do linux, antes havia qualquer Com sérias restrições de compatibilidade com versões anteriores, todas as chamadas do sistema foram renumeradas para otimizá-la no nível de uso do cacheline .

Eu não sei o suficiente sobre o desenvolvimento do kernel para saber a base específica para essas opções, mas aparentemente existe alguma lógica por trás da escolha de renumerar tudo com esses números específicos, em vez de simplesmente copiar a lista de uma arquitetura existente e remover os não utilizados. Parece que o pedido pode se basear na frequência com que são chamados - por exemplo, leitura / gravação / abertura / fechamento são antecipados. Saída e bifurcação podem parecer "fundamentais", mas cada uma delas é chamada apenas uma vez por processo.

Também pode haver algo acontecendo em manter as chamadas do sistema que são comumente usadas juntas na mesma linha de cache (esses valores são apenas números inteiros, mas há uma tabela no kernel com ponteiros de função para cada um, para que cada grupo de 8 chamadas do sistema ocupe uma linha de cache de 64 bytes para essa tabela)

Random832
fonte
1
fork may seem "fundamental", but [...] called only once per process.Uh o quê? Eu entendo que você pode esperar para chamar saída uma vez, mas você pode desembolsar dentro do pai e criança de um fork()apelo
gato
5
@cat, se você vê o item forksendo contabilizado no processo filho (ou seja, é a chamada de criação do processo), em vez do processo pai, a instrução Random832 está correta.
icarus 20/01
4
@cat OK, você pode chamar fork () duas ou três vezes, talvez mais algumas. Mas você pode ligar para read () milhões ou até bilhões de vezes.
Michael Hampton
1
Sim, foi o que eu quis dizer. O número de chamadas forquilha e o número de processos durante a vida útil do sistema vai ser idênticos, ignorando detalhes, como init, clone [que podem criar processos ou threads], etc.
Random832
15

Veja a resposta à pergunta "Por que os números de chamada do sistema são diferentes no amd64 linux?" no estouro de pilha.

Para resumir: por uma questão de compatibilidade, a lista de chamadas do sistema é estável e só pode crescer. Quando a arquitetura x86 64 apareceu, a ABI (passagem de argumento, valor retornado) era diferente, assim os desenvolvedores do kernel aproveitaram a oportunidade para trazer mudanças que há muito esperavam.

xhienne
fonte
Legal, meu palpite estava correto.
Ctrl-alt-delor
2
Essa outra resposta à qual você vincula é especulativa: diz "os caras do Linux provavelmente decidiram ..." (grifo nosso). Penso que ajudaria se a sua resposta aqui fornecesse alguma indicação de que aparentemente se baseia mais em especulações do que em evidências. Aliás, um comentário mais recente publicado sob a resposta vinculada fornece evidências de que o verdadeiro motivo não é a limpeza genérica de cruft (como especula essa resposta), mas é especificamente sobre o "uso de cacheline", conforme explicado na outra resposta aqui .
DW
-3

Em resumo, porque alguém pensou que " N+1maneiras incompatíveis de fazê-lo são melhores do que Nmaneiras". Para arcos históricos, os números de syscall geralmente eram escolhidos para corresponder a algum unix proprietário herdado. Mas para o x86_64, os desenvolvedores do kernel foram livres para escolher qualquer numeração que quisessem. Em vez de fazer a escolha simples e reutilizar uma numeração existente, eles fizeram a escolha de inventar um novo padrão. Então eles fizeram isso novamente para aarch64 e muitos outros. Esse é um padrão frequentemente repetido no desenvolvimento do kernel do Linux.

R ..
fonte
3
A mudança não foi gratuita. Existem sólidas razões técnicas. Se não fosse por requisitos de compatibilidade com versões anteriores, mudanças semelhantes também seriam aplicadas às arquiteturas existentes.
Jörg W Mittag
A diferença na numeração é 100% gratuita. Não há vantagem técnica para nenhuma numeração específica.
R ..
2
Como essa outra resposta explica, os syscalls são agrupados de modo que os syscalls comumente usados ​​juntos compartilhem o mesmo cacheline na tabela syscall. E os números do syscall são escolhidos de forma que sejam índices simples nessa tabela. Teoricamente, poderíamos usar uma camada de indireção para dissociar a posição de um syscall na tabela syscall do número syscall, mas isso possivelmente consumiria uma parte dos ganhos de desempenho que obtivemos ao colocar syscalls quentes no mesmo cache.
Jörg W Mittag
@ JörgWMittag: E isso obviamente é otimização prematura e não uma melhoria mensurável. Veja quantos ciclos os syscalls levam e quantas linhas de cache eles expulsam. Salvar na melhor das hipóteses uma linha de cache da ordem da tabela não fará diferença.
R ..
2
@R .. "Eu escolhi a numeração em função das informações de criação de perfil do kernel tpcc com os populares DBMS e strace output de alguns aplicativos de rede e desktop." certamente soa como se houvesse medidas. No entanto, o autor não forneceu números ou explicou adequadamente a metodologia.
user45891