Kernel Linux com suporte a .exe e .class

Publicado: 11 de março de 2008 em GNU/LINUX

Introdução

Não é novidade para ninguém que, com o uso do wine, e as configurações corretas, e possível executar muitos binários windows (.exe) no Linux. Quanto a executar um compilado java (.class), também não é em nada diferente de qualquer outra plataforma com suporte a java, ou seja, basta passar o nome da classe como argumento para o interpretador java.

Agora, o que acharia se eu dissesse que é possível configurar o kernel de tal forma que, para executar qualquer um desses formatos, bastaria digitar na linha de comando algo como:

/mnt/fat/windows/notepad.exe

ou

.
/alomundo.class

Interessante não? E não somente interessante, mas perfeitamente possível através de uma configuração que permite ao próprio kernel chamar um interpretador adequado para certos gêneros de arquivo. Ou seja, a dependência do wine e do interpretador java continuarão existindo,mas a diferença é que você não vai mais precisar se preocupar com eles, chamando diretamente o nome do binário. Para tanto você vai precisar de certo conhecimento na compilação do kernel (dependendo se sua distro já vem com a característica que descreverei a seguir compilada no kernel ou não), além de já ter configurados o ambiente java e/ou o wine na sua máquina (nada impede que você use este roteiro para configurar o suporte a apenas um dos tipos descritos).

Onde o kernel guarda o segredo

Após baixar os fontes do kernel, dependendo se está usando o kernel 2.4 ou 2.6, procure pelos seguintes menus:

  • kernel 2.4 > General Setup -> Kernel support for MISC binaries
  • kernel 2.6 > Executable file formats -> Kernel support for MISC binaries

Habilitar este item e recompilar o kernel é o primeiro passo para tornar isto possível. Esse item pode ser compilado direto no kernel ou como módulo, caso em que você terá que carregar o módulo com modprobe. Todos os testes que eu fiz foi com esse recurso já compilado dentro do próprio kernel, e este roteiro vai se ater a essa situação. As configurações mostradas foram testadas utilizando uma máquina Slackware 10, rodando ora kernel 2.4.26 ora kernel 2.6.12, que eram as versões mais recentes disponíveis para download em http://www.kernel.org no momento da finalização deste documento. Entretanto, se voce preferiria pular a etapa de recompilar o kernel caso sua distribuição ja tivesse esse recurso, e deseja fazer um teste para determinar isso, execute o comando mount da proxima sessão. Se ele executar sem erros, então você provávelmente pode pular esta etapa e ir direto para a parte fácil.

Conversando com o kernel

Decerto muitos já sabem que o diretório /proc é uma interface com o kernel, já que a maioria já deu cat em “arquivos” ali como cpuinfo,meminfo, e outros conhecidos. O que talvez vá ser novidade para alguns é que é possível também executar algo como:

echo parametro > /proc/alguma_coisa

De forma realmente configurar um parâmetro do kernel. Sim, o kernel também e configurável enquanto está executando, modificações não estão limitadas ao momento da compilação do mesmo. E é justamente através deste recurso que se pode informar o kernel de outros formatos binários suportados pela instalação do linux e onde está o interpretador para o mesmo. Primeiro, antes de executar um comando como o acima, e preciso montar a parte do /proc onde se irá atuar e, para tanto, execute o comando:

mount binfmt_misc -t binfmt_misc /proc/sys/fs/binfmt_misc

Se este comando retornar sem erros, você terá a partir daí dentro do diretório:

/proc/sys/fs/binfmt_misc

as entradas: register e status.

Se você executar um cat em /proc/sys/fs/binfmt_misc/status, receberá apenas o texto “enabled” como resposta, dizendo que o suporte a binfmt_mis está habilitado. Mas é register que nos interessa mais agora, pois será ele que usaremos para notificar o kernel de novos formatos binários. Mas antes uma última coisa sobre este mount: e possivel fazer com que ele seja executado automaticamente no boot apenas adicionando a seguinte linha ao /etc/fstab:

none /proc/sys/fs/binfmt_misc binfmt_misc defaults 0 0

Seja lá qual tenha sido o método usado, uma vez montado esse diretório, o próximo comando será o “echo” falado hà pouco:

echo REGISTRO > /proc/sys/fs/binfmt_misc/register

Sendo que REGISTRO será um conjunto de campos separados pelo caracter ‘:’ no seguinte formato:

:NOME:TIPO:OFFSET:PADRAO:MASCARA:INTERPRETADOR:

Desses 6 registros, apenas 4 são realmente necessários, mas segue uma breve explicação de cada um:

  • NOME = (necessário) Um identificador para este registro, escolha um nome que lembre o tipo de executável que você estará configurando como JAVA_CLASSE ou WINDOWSEXE. Surgirá um novo arquivo no mesmo diretório onde estão o status e register, com o mesmo nome deste identificador.
  • TIPO = (necessário) Diz ao kernel que mecanismo será utilizado para reconhecer o arquivo como deste tipo binário. Este campo só tem uma letra, sendo E ou M. Se for E, o kernel discernirá o binário por sua extensão, tal como .exe ou .class. Se for M, o kernel olhará dentro do arquivo procurando por uma determinada sequência de bits para reconhecer o formato. Por ser relativamente mais complexo, este último caso não será abordado aqui, e todas as configurações serão feitas de forma que o kernel reconheça o arquivo por sua extensão.
  • OFFSET = (opcional) Este campo só faria sentido se o anterior fosse M, pois trata-se da distância a partir do início do arquivo onde começar a olhar para procurar pelo padrão binário.
  • PADRAO = (necessário) Se TIPO for E, como será em todas as configurações que faremos, este campo deve conter a extensão sem o ponto. Ou seja, exe ou EXE para executáveis windows, class para java. Se TIPO fosse M, aqui seria colocada a sequência de bytes a ser procurada no arquivo.
  • MÁSCARA = (opcional) Também somente faria sentido se TIPO fosse M, pois este campo permite desabilitar (mascarar) alguns bits da sequência a ser procurada.
  • INTERPRETADOR = (necessário) trata-se do nome e caminho completo do interpretador para esse tipo de arquivo, tal como, por exemplo, /usr/lib/java/bin/java. Por fim, repare bem que o registro começa e termina com o caracter ‘:’. Uma vez dado o comando echo para salvar esse registro em /proc/sys/fs/binfmt_misc/register, aparecerá um novo arquivo em /proc/sys/fs/binfmt_misc com o mesmo nome do campo NOME no registro. Se não aparecer, veja se foi feita alguma incorreção na hora de formar o registro. Conceitos assimilados, está na hora de por isto na prática…

Fazendo o kernel “executar” o Windows

Os executáveis do windows na verdade🙂. No meu ambiente, eu instalei o wine baixando os fontes e executando wineinstall. O wine foi configurado para usar uma partição do Windows 98(R) como diretório do windows, que no meu linux ficou montado em /mnt/fat com direitos de acesso para leitura e escrita por usuários comuns. Segue a linha do meu fstab referente a essa partição:

/dev/hda1 /mnt/fat vfat user,umask=000,exec,dev,suid 1 0

Assim, o próximo passo foi executar:

$ echo :WINDOWS_EXE:E::exe::/usr/local/bin/wine: > /proc/sys/fs/binfmt_misc/register

E, como primeiro teste para ver se deu certo, executar:

$ cat /proc/sys/fs/binfmt_misc/WINDOWS_EXE
enabled
interpreter /usr/local/bin/wine
extension .exe

Até aqui tudo bem, então o teste final foi:

$/mnt/fat/windows/notepad.exe

E voilá, o notepad apareceu bem diante dos meus olhos🙂

Domando o Java

Bom, agora talvez alguém pensasse que nem é preciso explicar o java, pois o procedimento seria análogo ao usado com o wine, correto? Incorreto! Simplesmente registrar o caminho para o interpretador java seguindo a receita mostrada e tentar executar o arquivo class desta vez não vai dar certo. E não vai dar certo por um motivo simples: quando o kernel reconhece um tipo que deve ser tratado por um interpretador especificado deste modo, ele simplesmente executa o interpretador passando para o mesmo o nome e caminho para o arquivo. Agora eu pergunto aos ententidos de java de plantão, se eu executar algo como:

java /home/germano/minhaclasse.class

Isso vai funcionar? Não vai porque para o interpretador java não deve ser passado o nome do arquivo da classe, mas o nome da classe em si e apenas, sem diretórios. E o diretório onde está o arquivo .class deve estar configurado numa variável de ambiente chamada CLASSPATH. Bem, infelizmente ensinar java prolongaria demais este roteiro, de forma que me limitarei apenas a dizer que, no meu ambiente de teste, o interpretador está em /usr/lib/java/bin/java e minha variável de ambiente CLASSPATH está configurada como segue:

$echo $CLASSPATH
/usr/lib/java/lib:./

Para resolver esse tipo de situação a saída é escrever um wrapper, que nada mais é que um script que chama o interpretador com o argumento correto, e registrar esse wrapper no kernel como sendo o interpretador. No caso do java, eu escrevi o seguinte script e salvei em /usr/local/bin/javawrapper.sh

#!/bin/bash
NOMECLASSE=`echo $1 | tr / . | awk -F. '{print $(NF-1)}'`
/usr/lib/java/bin/java $NOMECLASSE

Este script é que será chamado pelo kernel e receberá como argumento o nome e caminho para o arquivo .class. As duas linhas de código cortam a extensão e o caminho do argumento recebido deixando apenas o nome da classe, e usa esse valor como argumento para o interpretador java.Contornada essa peculiaridade do java, bastou registrar o wrapper como teria feito com o próprio interpretador:

echo :JAVACLASS:E::class::/usr/local/bin/javawrapper.sh: >/proc/sys/fs/binfmt_misc/register

Depois disso compilei o seguinte programa java estilo alo mundo:

public class binfmt{
public static void main(String args[]){
System.out.println("O Linux e muito esperto
");
}
}

E por fim foi só chamar diretamente o arquivo .class para testar:

$ /home/germano/binfmt.class
    O Linux e muito esperto
 $ ./binfmt.class

    O Linux e muito esperto   Fonte

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s