FreeBSD vs Linux: desempenho das convenções de chamada do kernel

FreeBSD vs Linux: desempenho das convenções de chamada do kernel

Deint80h.org, o tutorial da linguagem assembly do FreeBSD

A convenção [Linux Calling] tem uma grande desvantagem em relação ao modo Unix, pelo menos no que diz respeito à programação em linguagem assembly: toda vez que você faz uma chamada ao kernel, você deve enviar os registradores e acioná-los mais tarde. Isso torna seu código mais volumoso e lento.

Continuando, diz sobre o suporte do FreeBSD tanto à convenção Linux quanto à "Convenção Unix"

Se você estiver codificando especificamente para o FreeBSD, você deve sempre usar a convenção Unix: é mais rápida, você pode armazenar variáveis ​​globais em registros, não precisa marcar o executável e não impõe a instalação do pacote de emulação do Linux. o sistema alvo.

Parece-me estranho que o modo Linux seja mais volumoso e lento. Parece que existem duas opções,

  • Salve apenas os registros que você precisa preservar, que são
    • aqueles registros voláteis que podem ser derrotados pela chamada do sistema (que eu saiba ecx)
    • ou, os registradores necessários para enviar os argumentos apropriados ao kernel para fazer o syscall(que pode ser eax, ecx, edx, esi, edi, ebp)
  • Salve 100% dos argumentos do kernel na pilha.

Parece que o FreeBSD é opiorcenário de caso da convenção Linux. o que estou perdendo? Como a convenção do FreeBSD (que eles chamam de "modo Unix") é menos volumosa e mais rápida?

Responder1

Isso realmente se resume à opinião do autor, na minha opinião.

Na convenção do FreeBSD (“Unix”), você coloca os argumentos na pilha, especifica o número de chamada do sistema EAXe invoca a interrupção 0x80 (com um operando extra na pilha porque espera ser chamado de uma função separada).

Na convenção Linux i386, você coloca os argumentos nos registros apropriados e invoca a interrupção 0x80.

O argumento volumoso/lento presumivelmente vem do fato de que com a convenção Linux, ochamadorprecisa lidar com o uso de registros. Se a chamada do sistema precisar de argumentos em registros que contenham valores importantes para o chamador, ela precisará preservá-los, o que resulta em trabalho braçal adicional;veja este exemplo da biblioteca C. Neste exemplo, a chamada do sistema precisa de valores em EAX, EBX, EDX, EDI e ESI; mas o chamador só se preocupa em preservar EBX, EDI e ESI, portanto, apenas os envia para a pilha. O caso geral éum pouco mais complexo(mas isso também é o resultado de lidar com uma mistura de C e linguagem assembly, tentando gerar o código ideal em todos os casos), porém ao escrever em linguagem assembly, que é o objetivo do site ao qual você está se referindo, isso não aconteceria. não seja um problema tão grande.

Parece-me que são seis e meia dúzia: na convenção do FreeBSD, você empurra para a pilha em todos os casos, na convenção do Linux, você empurra para a pilha (ou em outro lugar), dependendo do que você está fazendo por aí o local da chamada. Você poderia argumentar que a convenção do Linux permite código mais rápido, já que você pode realizar todos os seus cálculos em registradores... ComoRoubarressalta, no entanto, que no Linux os registros ainda acabam sendo empurrados (para construir a struct pt_regsinstância que é usada para fornecer os argumentos para as funções C que lidam com as chamadas do sistema), então o custo geral é maior no lado do Linux do que no lado Lado do FreeBSD.

De qualquer forma, discutir sobre desempenho ao falar sobre código baseado em pilha ou registro em torno de uma chamada de sistema parece bastante pedante, dado o custo de realizar a chamada de sistema em si. Qualquer ciclo salvo é obviamente bom em termos absolutos, mas a melhoria relativa será mínima.

informação relacionada