Como o Wine funciona 101
(werat.dev)- O Wine é uma camada de compatibilidade que permite executar programas do Windows em sistemas operacionais compatíveis com POSIX (Linux, macOS, BSD)
- O Steam Deck da Valve também usa uma solução baseada em Wine
WINE = Wine Is Not an Emulator
- A abordagem de emulação é lenta e, na prática, Linux/macOS conseguem executar binários do Windows nativamente (com uma pequena ajuda)
- Explica em detalhes, com um depurador, como binários de Linux/Windows funcionam
Hello, Wine!
- Basicamente, o Wine é um "dynamic loader" para executáveis do Windows
- É um binário Linux nativo e sabe como processar EXE e DLL
- O Wine carrega o executável do Windows na memória, faz o parsing, identifica dependências e salta para o código que deve ser executado
- Só isso já permite executar binários do Windows, mas há exceções
System Calls
- As chamadas de sistema, chamadas de
syscalls, são o que torna o Wine complexo syscallssão implementadas pelo sistema operacional, não ficam dentro do executável ou da biblioteca- As
syscallsfornecidas pelo SO são a API do sistema operacional- Linux:
read,write,open,brk,getpid,.. - Windows:
NtReadFile,NtCreateProcess,NtCreateMutant,..
- Linux:
- Chamadas de sistema são diferentes de chamadas normais de função no código. Por exemplo, abrir um arquivo precisa ser tratado pelo kernel porque ele acompanha o File Descriptor
- Portanto, o código da aplicação precisa de uma forma de se "interromper" e entregar o controle ao kernel ("context switch")
- O conjunto de funções fornecido pelo SO e a forma de chamá-las variam entre sistemas operacionais
- No Linux, ao chamar a função
read(), é preciso colocar o descritor de arquivo no registrador%rdi, o ponteiro do buffer em%rsie a quantidade de bytes a ler em%rdx - Já no Windows, a função
read()não existe no kernel
- No Linux, ao chamar a função
- Se executarmos o mesmo código que imprime "Hello World!" em Linux/Windows
- No Linux, ele chama
putsdelibc.so; no Windows, chamaprintfdeucrtbase.dll - Hoje em dia, no Linux, é comum fazer link estático e incluir a implementação de
putsdentro do binário, entãolibc.sonem é usado em tempo de execução
- No Linux, ele chama
- No Windows, pelo menos até recentemente, "só malware usava chamadas de sistema diretamente"
- Aplicações comuns sempre dependem de
kernel32.dll/kernelbase.dll/ntdll.dllpara não se comunicar diretamente com o kernel
- Aplicações comuns sempre dependem de
Runtime translation of Syscalls
- E se interceptarmos as
syscalls?
E se, quando a aplicação chamarNtWriteFile(), entrarmos no meio, chamarmoswrite()e depois retornarmos no formato de resultado que o binário espera? - Isso seria possível se fornecêssemos uma versão customizada de
ucrtbase.dll, mas surgem problemas complexos - Em vez disso, modifica-se a
ntdll.dll, que fica entre o binário e o kernel - Versões recentes do Wine são compostas por
ntdll.dll(binário PE) entdll.so(binário ELF)- A DLL é uma camada fina que apenas redireciona a chamada para o lado ELF
- O ELF tem uma função especial chamada
__wine_syscall_dispatcher, que faz a mágica de converter a pilha atual de Windows para Linux, ou vice-versa
- Esse syscall dispatcher é a ponte que liga o mundo Windows ao mundo Linux
- Ele lida com convenções de chamada, aloca espaço de pilha, move registradores e faz outras tarefas do tipo
- Quando a execução chega em
ntdll.soe passa para o binário Linux, passamos a poder usar todas as APIs do Linux
É só isso?
- Parece muito simples, mas...
- A API do Windows é enorme, mal documentada, tem bugs conhecidos e desconhecidos, e eles precisam ser preservados exatamente como são. A maior parte do código do Wine é a implementação de várias DLLs do Windows
- Existem várias formas de fazer chamadas de sistema e, tecnicamente, não há como impedir que aplicações chamem
syscallsdiretamente
(Lembre-se: jogos de Windows fazem todo tipo de loucura)
O kernel do Linux tem mecanismos especiais para lidar com isso e, claro, isso aumenta ainda mais a complexidade - O problema de 32 bits vs 64 bits também é um absurdo. Existem inúmeros jogos de 32 bits, e eles não vão ser relançados em 64 bits. Como o Wine suporta os dois, isso também aumenta a complexidade
- Nem chegamos a falar do
wine-server. É um processo separado criado pelo Wine, que mantém o "estado" do kernel (descritores de arquivo, mutexes etc.) - Quer executar jogos? Aí é preciso lidar com DirectX, PulseAudio, dispositivos de entrada e muito mais, então o trabalho cresce enormemente
- O Wine vem sendo desenvolvido há muito tempo e percorreu um longo caminho. Hoje, já consegue rodar jogos modernos como Cyberpunk 2077 e Elden Ring sem problemas
Às vezes, o Wine chega até a apresentar desempenho melhor que o Windows
11 comentários
Mais do que o conteúdo em si, a qualidade do resumo é realmente impressionante. Obrigado.
Estou usando o yes24 e a Kyobo Bookstore, que oferecem serviços de leitura por assinatura.
Depois de mudar o ambiente do PC de casa para Ubuntu, tentei executar o YES24 e a Kyobo Bookstore usando o Wine.
Os dois usam DRM próprio, então eu fiquei em dúvida se iriam rodar, mas o YES24, que acredito ter sido feito com Qt, funcionou bem, enquanto o ebook da Kyobo Bookstore não funcionou. (a interface abre, mas o DRM não roda)
Eu sabia que os dois tinham DRM, então fiquei pensando no que fazia um funcionar e o outro não, mas vendo o texto acima acho que dá para entender mais ou menos (aquele meme do "entendi tudo perfeitamente" mais ou menos).
Fico feliz que, desde o Wine 5.0, o KakaoTalk rode sem nenhuma configuração. (independentemente de eu querer usar o KakaoTalk ou não..) Há alguns problemas na exibição de certas telas, mas recursos como envio de imagens pela área de transferência funcionam de forma integrada. No geral, parece que o Wine está mais focado em rodar jogos, mas é ótimo ver que ele também consegue executar bem vários aplicativos. Mesmo quando se fala em adotar Linux em órgãos públicos, nem sequer cogitarem uma versão Linux do KakaoTalk é algo meio... bem ruim.. Já a versão para Mac eles fizeram rapidinho..
Eu tinha uma noção geral, mas é incrível ver o Wine explicado com tanto detalhe assim... rs
Como o Wine geralmente consegue executar bem programas do Windows, será que também daria para pensar em criar aplicativos multiplataforma usando o Wine? (limitado a desktop)
Há muito tempo, pelo que eu sei, até o HWP da Hancom chegou a ser portado e lançado para Linux com base no Wine. (O R4 tinha uma camada separada de biblioteca de compatibilidade
win32, e se foi o R5 ou o 2002 que usou Wine eu já não lembro direito.)Por isso, por um tempo, existia até a piada de que, graças ao Wine, o
win32era a API multiplataforma mais popular e bem-sucedida.Mas agora é a era do electron/wasm ;;;
Uma história um pouco diferente, mas, se você pretende fazer isso — como a licença do Wine é LGPL, dependendo de como o código for escrito, talvez seja necessário divulgar parte ou a totalidade do código-fonte.
Como também é explicado no texto original, o motivo de o Wine não ser um emulador é que ele usa as instruções da CPU diretamente. Isso significa que, basicamente, o software que pode ser executado com o Wine é software para Windows que roda em CPUs x86 ou x86-64.
Num momento em que a Apple já migrou toda a linha Mac para a arquitetura ARM, e a própria MS também está lançando kits de desenvolvimento baseados em ARM, talvez seja um pouco forçado chamar de “suporte multiplataforma” um software que só funciona em CPUs baseadas em x86(-64).
Sim. Como você disse... acho que acabei limitando isso, sem perceber, a máquinas da família x86.
Com a existência de Electron e Tauri, se fosse preciso criar algo multiplataforma do zero, parece que não seria uma boa escolha. Se houver alguma limitação específica que impeça o uso de tecnologias baseadas em navegador web, o uso de uma biblioteca como Qt, que oferece bom suporte a cross-compiling, talvez seja melhor..
222