Como o OSX executa binários de 64 bits durante a execução em um kernel de 32 bits?

4

Eu descobri recentemente que o Mac OS X pode executar aplicativos de 64 bits (x64) mesmo se o kernel x86 estiver carregado. Isso foi chocante para mim pela primeira vez.

Mas então eu percebi que é realmente estranho se o sistema está funcionando e sob CPU compatível com x64 não pode executar aplicações x64, não importa o kernel gerenciando os processos. Isso é realmente tão difícil? Basta carregar o maldito aplicativo na memória e configurar o ponteiro de operação da CPU para o primeiro byte, fácil como uma torta!

A primeira e única barreira para fazer isso, como eu poderia imaginar, é algum tipo de "cabeçalho executável". Infelizmente, não estou muito confortável com a arquitetura do Windows e a estrutura binária, por isso preciso de mais explicações aqui.

De fato, o padrão de cabeçalho binário do SO semelhante ao UNIX ELF tem seu irmão ELF64, que (como o documento aqui descreve) não tem muitas diferenças com o ELF32, mas mesmo que os kernels de 32 bits não consigam executar o código x64. Sim, este programa provavelmente está ligado a bibliotecas x64 e vamos imaginar que acabamos de copiá-los e colá-los na pasta / usr / lib64. Mas tenho certeza que isso não ajuda, por quê?

E, finalmente, o que há de tão especial no kernel do Mac OS X para que não se preocupe com o uso do conjunto de instruções do programa? O Mac OS X tem alguns universais e adequados para ambos os kernels executáveis cabeçalho, por isso só pode carregar o aplicativo na memória e dizer para a CPU "executar a partir daqui, eu não me importo o que significa que"?

P.S: Eu realmente pensei muito sobre onde colocar essa questão: no stackoverflow.com ou no superuser.com, e decidi colocar aqui, porque o tópico provavelmente é mais específico do sistema operacional.

    
por pechenie 27.09.2011 / 22:08

4 respostas

2

A verdadeira questão seria por que alguns outros sistemas operacionais não podem executar binários de 64 bits em um kernel de 32 bits. Não há razão fundamental para que isso não seja possível. A arquitetura do processador subjacente suporta tanto um conjunto de instruções de 64 bits (amd64 aka x86-64) quanto um conjunto de instruções de 32 bits (i386), e não há restrição para os dois serem usados juntos (em particular, não há "Modo de 64 bits" separado de um "modo de 32 bits"; há um único modo longo , que permite instruções tanto do i386 quanto do conjunto “nativa” amd64.

A execução de aplicativos de 64 bits em um kernel de 32 bits requer um pouco mais de trabalho dentro do kernel, pois ele deve gerenciar ponteiros de 64 bits para o espaço do usuário junto com ponteiros de 32 bits para o espaço do kernel. A maioria, se não todos, os ponteiros passados no kernel são conhecidos como sendo para o espaço do kernel ou conhecidos para o espaço do usuário, portanto, não é um problema se eles tiverem tamanhos diferentes. A principal dificuldade é abrir mão da possibilidade de ter um tipo de ponteiro universal que possua intervalos separados de valores para memória de processo, memória do kernel e memória usados por várias peças de hardware (incluindo RAM), mas isso não é possível em kernels recentes de 32 bits no hardware de classe de PC, se você tiver 4 GB ou mais de RAM, ou quiser mapear 2 GB de RAM mais 2 GB de espaço de processamento, mais memória de kernel e mais, você precisa ser capaz de mapear endereços de mais de 32 bits. ).

De acordo com o artigo da Wikipedia que você cita, o OSX tinha a capacidade de executar processos amd64 em amd64 processadores antes de ter um kernel de 64 bits. O Solaris também mistura indiferentemente os executáveis i386 e amd64 em processadores amd64, independentemente de o kernel ser de 32 ou 64 bits (ambos disponíveis).

Outros sistemas operacionais podem executar processos i386 em um kernel amd64 (64 bits), mas não em processos amd64 em um kernel de 32 bits, por exemplo, Linux, FreeBSD, NetBSD e Windows. No entanto, outros sistemas operacionais tratam amd64 e i386 como arquiteturas completamente diferentes, por exemplo, o OpenBSD.

    
por 27.09.2011 / 23:59
4

Não estou familiarizado o suficiente com a arquitetura x86_64 para dar detalhes, mas essencialmente o que acontece é que a CPU é alternada entre o modo de 64 bits e o modo de compatibilidade (32 bits) como parte da troca de contexto entre o kernel e um programa de espaço do usuário. Isso é basicamente a mesma coisa que seria feita para executar um programa de 32 bits em um kernel de 64 bits, apenas acontecendo ao contrário.

BTW, o OS X não usa o formato binário ELF, ele usa binários Mach-O . O formato Mach-O permite binários de múltiplas arquiteturas ("universais"), portanto os programas (e também o kernel) podem ser fornecidos em 32 e 64 bits (e PPC e PPC64 e ...), e o SO pode escolha qual versão carregar (e, portanto, em qual modo executá-la) no momento do carregamento. Você pode usar o comando file em um binário para ver em quais formatos ele está. Por exemplo, aqui está o aplicativo de xadrez enviado com o OS X v10.5:

$ file Applications/Chess.app/Contents/MacOS/Chess 
Applications/Chess.app/Contents/MacOS/Chess: Mach-O universal binary with 4 architectures
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc): Mach-O executable ppc
Applications/Chess.app/Contents/MacOS/Chess (for architecture ppc64):   Mach-O 64-bit executable ppc64
Applications/Chess.app/Contents/MacOS/Chess (for architecture i386):    Mach-O executable i386
Applications/Chess.app/Contents/MacOS/Chess (for architecture x86_64):  Mach-O 64-bit executable x86_64

E uma nota para aqueles que duvidam que isso seja possível: OS X suportou programas de 64 bits a partir da v10.4 (com suporte limitado a API), mas não incluiu um kernel de 64 bits até a v10.6 (e mesmo então, o kernel rodou no modo de 32 bits por padrão na maioria dos modelos). Consulte o guia de transição de 64 bits da Apple para obter detalhes. Estou postando isso de um MacBook Pro executando 10.6 com um kernel de 32 bits (64 bits não é suportado para este modelo em particular), mas de acordo com o Activity Monitor, o processo somente não está em execução em 64 O modo de bits é o kernel_task.

    
por 27.09.2011 / 23:54
3

Os Macs suportam a execução de aplicativos de 64 bits em cima de um kernel de 32 bits porque um plano em vários estágios faz exatamente isso:

  1. Os aplicativos para Mac são fornecidos como "binários gordos" em "pacotes" que permitem que todos os quatro combos de 64/32 bits e Intel / PPC façam parte de uma única instalação, que pode ser tão simples quanto arrastar e soltar. O sistema operacional executa o apropriado.
  2. Os Macs usam o PAE para acessar mais de 4 GB de RAM ao executar um kernel de 32 bits. O Windows não permite a PAE em versões que não são do servidor devido a problemas de compatibilidade com drivers, que eles têm muito mais, incluindo os de terceiros.
  3. O Tiger adiciona uma ABI (Application Binary Interface) de 64 bits para executar o código de 64 bits na parte superior do kernel de 32 bits e uma versão de 64 bits das APIs de baixo nível (Application Programming Interface) para "console "Aplicativos (não GUI).
  4. O Leopard adiciona o Cocoa de 64 bits para aplicativos GUI (mas não o Carbono de 64 bits).
  5. O Snow Leopard adiciona um kernel de 64 bits, que é o padrão em apenas alguns modelos de última geração.
  6. O Lion requer uma CPU de 64 bits, mas ainda inclui o kernel de 32 bits. Um Mac antigo com uma CPU de 64 bits, mas uma GPU que tenha apenas drivers de 32 bits, teria que executar o kernel de 32 bits, por exemplo.

Assim, o OS X suportava aplicativos de 64 bits o mais rápido possível e continuava a executar o kernel de 32 bits o máximo possível devido à situação do driver. (O bit ness do kernel só se torna um fator ao tentar gerenciar grandes quantidades de RAM - as tabelas de páginas também recebem memória - e mudar para um kernel de 64 bits oferece alguns benefícios de desempenho.) Mas a Apple certamente não tem vergonha de coisas.

A verdadeira questão é por que o Windows e o Linux não fizeram a mesma coisa. Para o Windows, considere que sua primeira tentativa no Win64 foi com o Itanium, que era completamente diferente. Mas a resposta final pode se resumir ao que geralmente tem nas últimas décadas: compatibilidade com um monte de programas de terceiros que não fez as coisas do jeito certo :

OS X’s 64-bit implementation differs significantly from that of Windows, which treats its 32-bit and 64-bit versions as two distinct operating systems stored on different install media. This is done mostly to maintain Windows’ compatibility with older applications – moving or renaming things like the System32 folder would break programs that expected it to be there – and as a result the two are separated to the point that there isn’t even an upgrade path between 32-bit Windows and 64-bit Windows. Because of this, and because Windows applications and drivers usually have distinct 32-bit and 64-bit versions, Windows’ transition to 64-bit has been slightly rockier and slightly more visible to the user.

Há muitas informações em segundo plano sobre a transição de 64 bits no lado do Mac e o lado do Windows . (Esses links são para o último de cada série de artigos; não se esqueça de voltar ao início de cada um deles.)

Eu não sei qual foi a história com o Linux, mas imagine que Linus tenha uma opinião strong sobre isso.

    
por 28.09.2011 / 03:55
0

I've realized that it is really weird if system is up and running under x64 compatible CPU can't run x64 applications, no matter what kernel managing the processes. Is it really so hard? Just load damn app into the memory and set up the CPU operation pointer to the first byte, easy as pie!

Você está perdendo uma parte importante. Os aplicativos fazem chamadas de API para funções e serviços fornecidos pelo sistema operacional. Se um aplicativo de 64 bits envia um ponteiro de 64 bits para um sistema operacional de 32 bits, as coisas devem explodir.

Eu suspeito que, para fazer as coisas funcionarem de maneira aceitável, o SO deve sobrecarregar a função e fornecer uma versão de 64 bits e 32 bits de cada função. Para cada kernel, a função "off" (função de 64 bits em kernels de 32 bits, 32 bits em kernels de 64 bits) será apenas um stub que converte a chamada em segurança de 32 bits e chama novamente a função nativa.

    
por 28.09.2011 / 04:03