Mudança do kernel do WSL afim de adicionar uma chamada de sistema Hello World
Para realizar esse trabalho prático utilizou-se o WSL2 na distribuição Ubuntu 20.04 que tem o kernel base 5.10.16.3-microsoft-standard-WSL2. Para saber o kernel basta digitar:
uname -r
ou
sudo apt install neofetch
neofetch
Para realizar essa etapa é necessário utilizar o Git e clonar o repositório da Microsoft, WSL2-Linux-Kernel:
#Instalação do git para clonagem de repositórios
sudo apt install git
mdkir kernel && cd kernel
git clone https://github.com/microsoft/WSL2-Linux-Kernel.github
cd WSL2-Linux-Kernel
A pasta kernel pode ser criada em qualquer lugar já que compilaremos em cima dela e o executável será movido para a pasta raiz do Windows e lá faremos alterações com auxílio do PowerShell.
No diretório WSL2-Linux-Kernel, gerado pelo clone da etapa passada, crie um diretório hello e dentro desse um arquivo hello.c.
mkdir hello && cd hello
Para manipular o arquivo hello.c utilizaremos qualquer editor de texto pré-instalado pelo Linux, como nano, pico ou vi.
hello.c
copiando o seguinte código:
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE0(hello)
{
printk("Hello World.\n");
return 0;
}
Esse código contem o printk que é uma função C da interface do kernel Linux que imprime mensagens no log do kernel. Então, ao final do processo, ao ver as mensagens do buffer do kernel, quando o código for compilado e executado, Hello World deverá aparecer. O SYSCALL_DEFINE0 irá definir a chamada de sistema para o hello que estamos criando.
Como o kernel do linux tem vários Makefiles devemos avisar qual é o arquivo de origem ao arquivo objeto gerado e para isso criamos um Makefile $touch Makefile
e colocamos o seguinte código:
echo "obj-y := hello.o" > Makefile
Nisso voltamos uma pasta $ cd ..
para manipular o Makefile principal e ao editar com o $nano Makefile
procuraremos a segunda aparição do core-y nesse arquivo. Ele estará com os seguintes módulos:
kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
e o objetivo é adicionar o hello após o block
kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/ hello/
Antes de compilarmos e instalarmos devemos adicionar a nova chamada na biblioteca de syscalls do linux, portanto:
nano include/linux/syscalls.h
e chegando no #endif, presente na última linha do arquivo, acima dele adicionaremos:
asmlinkage long sys_hello(void);
Por fim, adicionamos a chamada na tabela de chamadas de sistema, e para isso:
nano arch/x86/entry/syscalls/syscall_64.tbl
e na última chamada adicionamos o nosso hello, é provável que tenha 547 chamadas no kernel, portanto:
548 common hello sys_hello
Para essa etapa precisamos instalar:
sudo apt install build-essential flex bison dwarves libssl-dev libelf-dev
Terminada a instalação, para compilarmos, o seguinte código se faz necessário:
make KCONFIG_CONFIG=Microsoft/config-wsl
O código acima pode ser modificado de acordo com a quantidade de processadores, para saber a quantidade, pode-se utilizar o aplicativo cpu-z. Note que se usar todos, o computador ficará extremamente lento.
$make KCONFIG_CONFIG=Microsoft/config-wsl -j4
O processo dura entorno de 30 a 180 minutos. Se durante o processo houver uma interrupção de escolha, escolha sempre o padrão.
Se ocorrer o erro 255 significa que utilizou-se muita memória (chegou perto de 2.5GB) e o processo foi interrompido, para isso há duas soluções, ou aprimora-se a memória do WSL ou desativa-se os processos que rodam junto com o WSL como por exemplo o Docker. Para identificar que chegou perto de 2.5GB basta usar $dmesg | grep pahole
Independente da escolha, recomece a compilação:
O processo é bem sucedido se a última mensagem for favorável (ready).
Após a compilação um arquivo chamado vmlinux será gerado, esse é o nosso novo kernel e para isso copiamos ele para a pasta do usuário do windows pois lá criaremos um arquivo do wsl para configuração, para isso:
sudo cp vmlinux /mnt/c/Users/<Nome_Usuário>/
- No PowerShell
Abrindo o PowerShell, criaremos o arquivo .wslconfig:
code .wslconfig
e adicionaremos:
[wsl2]
kernel=C:\\Users\\<Nome_Usuário>\\vmlinux
Note que code só poderá ser chamado se o vscode estiver instalado, caso não o tenha, baixe ou utilize o notepad do Windows.
Por padrão, o wsl sempre apontará para a variável kernel, e nesse caso estamos apenas alterando seu valor com um caminho diferente do padrão. Agora o kernel é o vmlinux e ainda no PowerShell digitaremos:
wsl --shutdown <Nome_Distribuição>
- No Linux
Abrindo novamente a distribuição no wsl, e realizando o $uname -r
percebemos que o kernel foi alterado.
Criando um novo arquivo, $nano teste.c
, colocaremos este código:
#include <stdio.h>
#include <linux/kernel.h>
#include <sys/syscall.h>
#include <unistd.h>
int main()
{
long int amma = syscall(548);
printf("System call sys_hello returned %ld\n", amma);
return 0;
}
Realizando a compilação e a execução:
gcc teste.c
./a.out
obtemos a mensagem "System call sys_hello returned 0" e analisando o $dmesg
a última linha mostra um Hello World.