Capítulo 10. Compatibilidade binária com o Linux®

Esta tradução pode estar desatualizada. Para ajudar com as traduções, acesse a ferramenta de traduções do FreeBSD.

10.1. Sinopse

O FreeBSD fornece compatibilidade binária com o Linux™, permitindo que os usuários instalem e executem a maioria dos binários do Linux™ em um sistema FreeBSD sem ter que primeiro modificar o binário. Foi até relatado que, em algumas situações, os binários Linux™ têm melhor desempenho no FreeBSD do que no Linux™.

No entanto, alguns recursos do sistema operacional específicos do Linux™ não são suportados no FreeBSD. Por exemplo, os binários Linux™ não funcionarão no FreeBSD se usarem chamadas específicas i386™, mesmo ativando o modo 8086 virtual.

O suporte para compatibilidade binária de 64 bits com o Linux™ foi adicionado no FreeBSD 10.3.

Depois de ler este capítulo, você saberá:

  • Como habilitar a compatibilidade binária com o Linux™ em um sistema FreeBSD.

  • Como instalar bibliotecas compartilhadas adicionais do Linux™.

  • Como instalar aplicativos Linux™ em um sistema FreeBSD.

  • Os detalhes de implementação da compatibilidade com o Linux™ no FreeBSD.

Antes de ler este capítulo, você deve:

10.2. Configurando a compatibilidade binária com o Linux™

Por padrão, as bibliotecas do Linux™ não estão instaladas e a compatibilidade binária com o Linux™ não está ativada. As bibliotecas Linux™ podem ser instaladas manualmente ou a partir da coleção de Ports do FreeBSD.

Antes de tentar compilar o port, carregue o módulo de kernel Linux™, caso contrário a compilação irá falhar:

# kldload linux

Para compatibilidade com 64 bits:

# kldload linux64

Para verificar se o módulo está carregado:

% kldstat
      Id Refs Address    Size     Name
      1    2 0xc0100000 16bdb8   kernel
      7    1 0xc24db000 d000     linux.ko

O pacote ou port emulators/linux_base-c7 é a maneira mais fácil de instalar um conjunto básico de bibliotecas e binários do Linux™ em um sistema FreeBSD. Para instalar o port:

# pkg install emulators/linux_base-c7

Para que a compatibilidade com o Linux™ seja ativada durante a inicialização, adicione esta linha ao /etc/rc.conf:

linux_enable="YES"

Em máquinas de 64 bits, o /etc/rc.d/abi carregará automaticamente o módulo para emulação de 64 bits.

Como a camada de compatibilidade binária do Linux™ ganhou suporte para a execução de binários Linux™ de 32 e 64 bits (em hosts x86 de 64 bits), não é mais possível vincular estaticamente a funcionalidade de emulação a um kernel personalizado.

10.2.1. Instalando Bibliotecas Adicionais Manualmente

Se um aplicativo Linux™ reclamar sobre a falta de bibliotecas compartilhadas após configurar a compatibilidade binária do Linux™, determine quais bibliotecas compartilhadas o Linux™ precisa e instale-as manualmente.

A partir de um sistema Linux™, o ldd pode ser usado para determinar quais bibliotecas compartilhadas o aplicativo precisa. Por exemplo, para verificar quais bibliotecas compartilhadas o linuxdoom precisa, execute este comando a partir de um sistema Linux™ que tenha o Doom instalado:

% ldd linuxdoom
libXt.so.3 (DLL Jump 3.1) => /usr/X11/lib/libXt.so.3.1.0
libX11.so.3 (DLL Jump 3.1) => /usr/X11/lib/libX11.so.3.1.0
libc.so.4 (DLL Jump 4.5pl26) => /lib/libc.so.4.6.29

Então, copie todos os arquivos listados na última coluna da saída do comando no sistema Linux™ para o diretório /compat/linux no sistema FreeBSD. Depois de copiados, crie links simbólicos para os nomes na primeira coluna. Este exemplo irá resultar nos seguintes arquivos no sistema FreeBSD:

/compat/linux/usr/X11/lib/libXt.so.3.1.0
/compat/linux/usr/X11/lib/libXt.so.3 -> libXt.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3.1.0
/compat/linux/usr/X11/lib/libX11.so.3 -> libX11.so.3.1.0
/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

Se uma biblioteca compartilhada Linux™ já existir com um número de revisão principal correspondente à primeira coluna da saída do comando ldd, ela não precisará ser copiada para a arquivo nomeado na última coluna, pois a biblioteca existente deve funcionar. No entanto é aconselhável copiar a biblioteca compartilhada se for uma versão mais nova. O arquivo antigo pode ser removido, desde que o link simbólico aponte para o novo.

Por exemplo, essas bibliotecas já existem no sistema FreeBSD:

/compat/linux/lib/libc.so.4.6.27
/compat/linux/lib/libc.so.4 -> libc.so.4.6.27

e o ldd indica que um binário requer uma versão posterior:

libc.so.4 (DLL Jump 4.5pl26) -> libc.so.4.6.29

Como a biblioteca existente tem apenas uma ou duas versões desatualizadas no último dígito, o programa ainda deve funcionar com a versão um pouco mais antiga. No entanto, é seguro substituir o libc.so existente pela versão mais nova:

/compat/linux/lib/libc.so.4.6.29
/compat/linux/lib/libc.so.4 -> libc.so.4.6.29

Geralmente, será necessário procurar as bibliotecas compartilhadas que os binários do Linux™ dependem apenas das primeiras vezes que um programa Linux™ é instalado no FreeBSD. Depois de um tempo, haverá um conjunto suficiente de bibliotecas Linux™ compartilhadas no sistema para poder executar binários Linux™ atualizados sem qualquer trabalho extra.

10.2.2. Instalando os binários Linux™ELF

Os binários ELF requerem por vezes um passo extra. Quando um binário ELF sem marca for executado, ele gerará uma mensagem de erro:

% ./my-linux-elf-binary
ELF binary type not known
Abort

Para ajudar o kernel do FreeBSD a distinguir entre um binário do FreeBSD ELF e um binário Linux™, use brandelf(1):

% brandelf -t Linux my-linux-elf-binary

Como o conjunto de ferramentas GNU coloca as informações de branding apropriadas em binários ELF automaticamente, essa etapa geralmente não é necessária.

10.2.3. Instalando um aplicativo baseado em Linux™RPM

Para instalar um aplicativo baseado em Linux™RPM, primeiro instale o pacote ou o port archivers/rpm4. Uma vez instalado, o usuário root pode usar este comando para instalar um .rpm:

# cd /compat/linux
# rpm2cpio < /path/to/linux.archive.rpm | cpio -id

Se necessário, use o brandelf nos binários ELF instalados . Observe que isso impedirá uma desinstalação limpa.

10.2.4. Configurando o Resolver do Hostname

Se o DNS não funcionar ou este erro aparecer:

resolv+: "bind" is an invalid keyword resolv+:
"hosts" is an invalid keyword

configure o /compat/linux/etc/host.conf como segue:

order hosts, bind
multi on

Isso especifica que o /etc/hosts deve ser pesquisado primeiro e o DNS deve ser pesquisado em segundo lugar. Quando o /compat/linux/etc/host.conf não existe, os aplicativos Linux™ usam o /etc/host.conf e avisam sobre a sintaxe incompatível do FreeBSD. Remova o bind se um servidor de nomes não estiver configurado usando o /etc/resolv.conf.

10.3. Tópicos Avançados

Esta seção descreve como funciona a compatibilidade binária com o Linux™ e é baseada em um email escrito para Lista de discussão do chat do FreeBSD por Terry Lambert tlambert@primenet.com (Message ID: <199906020108.SAA07001@usr09.primenet.com>).

O FreeBSD tem uma abstração chamada "loader de classes de execução". Esta é uma cunha na chamada de sistema execve(2) .

Historicamente, o loader UNIX™ examinava o número mágico (geralmente os primeiros 4 ou 8 bytes do arquivo) para ver se era um binário conhecido pelo sistema e, em caso afirmativo, invocava o loader binário.

Se o arquivo não fosse o tipo binário adequado para o sistema, a chamada execve(2) retornava uma falha, e o shell tentava iniciar a execução do mesmo como um comando do shell. A suposição era um padrão de "qualquer que seja o shell atual".

Posteriormente, foi feito um hack para que o sh(1) examinasse os dois primeiros caracteres e se eles fossem :\n, ele invocava o shell csh(1) em seu lugar.

O FreeBSD tem uma lista de loaders, em vez de um único loader, com um fallback para o loader #! para executar interpretadores de shell ou scripts de shell.

Para o suporte ao Linux™ABI, o FreeBSD vê o número mágico como um binário ELF. O loader ELF procura por uma marca especializada, que é uma seção de comentários na imagem ELF e que não esteja presente nos binários ELF SVR4/Solaris™.

Para que os binários Linux™ funcionem, eles devem ser marcados como tipo Linux usando o comando brandelf(1):

# brandelf -t Linux file

Quando o loader ELF vê a marca Linux, ele substitui um ponteiro na estrutura proc. Todas as chamadas do sistema são indexadas por esse ponteiro. Além disso, o processo é sinalizado para manipulação especial do vetor trap para o código de trampolim de sinal, e vários outros (menores) reparos que são manipulados pelo módulo do kernel Linux™.

O vetor de chamada do sistema Linux™ contém, entre outras coisas, uma lista de entradas sysent[] cujos endereços residem no módulo do kernel.

Quando uma chamada de sistema é acionada pelo binário Linux™, o código de interceptação desreferencia o ponteiro de função de chamada do sistema da estrutura proc e obtém a classe Linux™, não a FreeBSD, como ponto de entrada para a chamada do sistema.

O modo Linux™ procura fazer reroots dinamicamente. Isso é, na verdade, equivalente ao union para montagens de sistema de arquivos. Primeiro, é feita uma tentativa de procurar o arquivo em /compat/linux/original-path. Se isso falhar, a pesquisa será feita em /original-path. Isso garante que os binários que exigem outros binários possam ser executados. Por exemplo, o conjunto de ferramentas Linux™ pode ser executado sob o suporte da Linux™ABI. Isso também significa que os binários Linux™ podem carregar e executar binários do FreeBSD, se não houver binários Linux™ correspondentes, e que o comando uname(1) pode ser colocado na árvore de diretórios /compat/linux para garantir que os binários Linux™ não possam dizer que não estão rodando em Linux™.

De fato, existe um kernel Linux™ no kernel do FreeBSD. As várias funções subjacentes que implementam todos os serviços fornecidos pelo kernel são idênticas às entradas da tabela de chamada do sistema FreeBSD, e às entradas da tabela de chamada do sistema Linux™: operações do sistema de arquivos, operações de memória virtual, entrega de sinal e System V IPC. A única diferença é que os binários do FreeBSD obtêm as funções de cola do FreeBSD, e os binários Linux™ recebem as funções de cola do Linux™. As funções de cola do FreeBSD estão estaticamente ligadas ao kernel, e as funções de cola do Linux ™ podem ser estaticamente ligadas, ou podem ser acessadas através de um módulo do kernel.

Tecnicamente, isso não é realmente emulação, é uma implementação de ABI. Às vezes é chamado de "emulação™ Linux " porque a implementação foi feita num momento em que não havia outra palavra para descrever o que estava acontecendo. Dizer que o FreeBSD executava os binários do Linux™ não era verdade, já que o código não era compilado nele.


Última alteração em: 9 de março de 2024 por Danilo G. Baio