Skip to main content

201.2 Compilando o Kernel



Para compilar seu próprio kernel você só precisa fazer três etapas: baixar o código fonte, ajustar a configuração de build de acordo com o hardware que pretende suportar e, por fim, compilar/instalar. O fluxo típico é o seguinte, e vale tanto para Debian/Ubuntu quanto para a família Red Hat:

# Debian/Ubuntu
sudo apt update
sudo apt install -y build-essential

# RHEL/Fedora/CentOS/Alma/Rocky
sudo dnf groupinstall "Development Tools"

O processo de build usa ferramentas de "tradução" para conseguir compilar o Kernel (também conhecido como parsers, que são Bison, Flex...), exige bibliotecas para a interface ncurses dos menus de configuração, além de cabeçalhos ELF, utilitários de criptografia e uma calculadora de precisão (bc) usados nos scripts Makefile. Precisamos instalar os pacotes abaixo para que seja possível compilar o Kernel, como explicado acima.

# comum em distribuições Debian-like
sudo apt install -y bison flex libncurses-dev libelf-dev bc libssl-dev

Se sua distribuição for Red Hat-like, muitos desses itens já vêm com Development Tools, o que faltar pode ser instalado individualmente (ncurses-devel, elfutils-libelf-devel, openssl-devel, etc.).


O kernel oferece várias interfaces para selecionar quais módulos vamos colocar ou não no nosso Kernel compilado, além de outras opções. Essas interfaces podem ser:

  • make menuconfig (ncurses): Funciona em qualquer terminal (requer libncurses-dev).
  • make xconfig (Qt): Interface gráfica; instale pkg-config, g++ e qt5-base-dev (ou libqt4-dev em sistemas mais antigos).
  • make gconfig (GTK): Alternativa em GTK2, precisa de libgtk2.0-dev, libglib2.0-dev e libglade2-dev.

Veja a relação de pacotes abaixo, na última linha, você encontrará todos os pacotes que devam ser instalados, mas no começo, terá uma explicação simples para cada pacote.

## Debian

## Para usar o xconfig (Qt) baixe os pacotes abaixo:
$ sudo apt install -y pkg-config g++ libqt4-dev bison flex

## Para usar o gconfig (GTK) baixe os pacotes abaixo:
$ sudo apt install -y libgtk2.0-dev libglib2.0-dev libglade2-dev


Configurando o Ambiente


Existem várias formas de compilar o Kernel, vou tentar passar por elas e demonstrar a melhor forma. Antes de começar a compilar o Kernel de fato, vamos preparar o ambiente da compilação:

# Entre em '/usr/src':
$ cd /usr/src

# Agora vamos baixar o código fonte do Kernel (no caso a versão estável do momento):
$ sudo wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.14.8.tar.xz

# Vamos descompactar usando o 'tar':
$ sudo tar xvf linux-5.14.8.tar.xz

# Crie um link simbólico apontando para o diretório do novo Kernel,
# isso vai facilitar nosso trabalho:
$ sudo ln -s linux-5.14.8 linux

# Entre na pasta do Kernel novo:
$ cd linux

Para compilar o kernel você precisa, antes de tudo, gerar um arquivo de configuração que diga ao sistema de build quais módulos, subsistemas e opções serão incluídos. Esse arquivo chama-se .config e fica na raiz do diretório onde está o código fonte. Cada linha tem o formato CONFIG_OPÇÃO=y/m/n, e o Makefile principal vai ler esse arquivo para decidir o que compilar, que flags passar ao GCC, que módulos instalar em /lib/modules/<versão>/ e assim por diante.


Para criar esse .config podemos fazer de duas formas, mais conhecidas são usando o make config e o make menuconfig, além desses dois, você ainda pode usar make xconfig ou make gconfig.


Ao executar qualquer um dos make acima, o sistema fará algumas perguntas (via linha de comando ou menu). Ao finalizar todas as perguntas e/ou configurações do que incluir ou não no Kernel, o sistema vai salvar tudo no .config. Na próxima vez que você usar o make, o próprio Makefile principal detecta a presença (ou mudança) desse .config, gera as dependências (include/config/ e autoconf.h) e então começa a compilar.


Na hora de escolher o que entra no kernel, cada item da árvore Kconfig declara o tipo de build que aceita. Em termos práticos você verá três situações:

  • Kernel-only (built-in)
    Aparece no menu com apenas duas opções: <*> para habilitado no Kernel ou < > para quando não for carregado no Kernel. Se marcar <*> a funcionalidade é compilada diretamente no binário do kernel. Se deixar em branco ela fica de fora. Não existe modo módulo para esse caso. Exemplos comuns são o agendador do kernel ou o driver "virtio-mmio" em arquiteturas que exigem inicialização precoce.

  • Modules-only
    São funcionalidades que só podem ser usadas no Kernel como módulos. Aparece no menu com apenas duas opções: <M> para carregado como módulo ou < > para quando não for carregado no Kernel. Ao marcar M o sistema gera um arquivo .ko dentro de /lib/modules/<versão>/, esse módulos não podem ser compilados como Kernel-only.

  • Tristate (built-in ou módulo)
    São funcionalidades que podemos escolher habilitar como módulo (<M>), habilitar diretamente no kernel como built-in (<*>) ou desativar.


Internamente o Kconfig deixa essas escolhas como o exemplo abaixo dentro de .config:

  • CONFIG_FOO=y → built-in
  • CONFIG_FOO=m → módulo externo
  • # CONFIG_FOO is not set → ausente

Para relembrar isso, consulta a seção módulos da LPIC-1.



Formas de configurar o ambiente para a compilação


  • make config

    É o modo mais root de configurar um ambiente para compilação, nele vamos responder o que colocar ou não junto com o Kernel, mas vamos responder pergunta por pergunta, no total são mais de 100 perguntas.


  • make menuconfig

    Com isso será exibido um menu via cli para que possamos marcar e desmarcar os módulo que queremos ou não no Kernel. Vamos ver como as opções são apresentadas:

    # Módulo será Built-in:
    [*] built-in

    # Módulo será removido da compilação:
    [ ] excluded

    # Módulo será carregado como um módulo:
    <M> module

    # Módulo será carregado como Built-in:
    <*> module

    Você pode clicar em Save (use o enter para selecionar), reponda Yes para salvar, toda essas perguntas serão salvas num arquivo chamado .config. Outra opção que temos aqui é o load, usado para importar um .config já existente.


  • make oldconfig

    Usado quando já temos um .config, esse arquivo pode ser uma instalação já padronizada, ou podemos pegar de outro Kernel que já foi configurado. Caso exista alguma nova pergunta que ainda não tem resposta, o configurador do ambiente irá fazer essa pergunta, isso acontece principalmente em novos Kernels.


  • make xconfig

    Utiliza um instalador gráfico baseado em Qt, é similar ao menuconfig, mas utiliza a interface gráfica.


  • make gconfig

    Utiliza um instalador gráfico baseado em GTK, é similar ao menuconfig, mas utiliza a interface gráfica.



Makefile


Para a maioria dos programas em C que você baixa, existe um script chamado configure, a função dele é vasculhar o sistema, verifica dependências e, ao final, cria (ou atualiza) um arquivo Makefile adaptado ao seu ambiente local. Esse Makefile é efêmero, ou seja, em cada execução de ./configure, você pode fornecer opções diferentes para o Makefile.


No Kernel, esse script não está disponível, já que o código fonte do Kernel vem com o Makefile para podemos iniciar a compilação, só precisando gerar o .config.


Uma das opções que podemos alterar no Makefile é o EXTRAVERSION =, ele é usado para inserir um sufixo ao número de versão do Kernel, criando uma versão nossa por exemplo. A string final que aparece em uname -r é montado assim: KERNELRELEASE = VERSION.PATCHLEVEL.SUBLEVEL EXTRAVERSION CONFIG_LOCALVERSION. Vou deixar essa opção como EXTRAVERSION = -rev1.


Além desse opção, existem outras que podemos modificar com relação a versão/nome do Kernel, a tabela abaixo exemplifica essas opções:

CampoValorO que significa, resumidamente
VERSION5Versão "major", indica o release principal do kernel. Mudanças aqui tendem a ser grandes.
PATCHLEVEL14Versão "minor", é uma atualização dentro do release acima, costuma trazer novos recursos para a versão acima.
SUBLEVEL8Pode ser um patch ou revisão de manutenção que corrige bugs e falhas de segurança para o major.minor (exemplo, versão 5.14).
EXTRAVERSION-rev1Sufixo opcional adicionado pelo mantenedor local para distinguir builds; aparece em uname -r e cria diretório exclusivo em /lib/modules/.
NAMEThe Linux is CrazyCodinome divertido que a equipe do kernel associa a essa versão, é um valor puramente simbólico.


.config


O arquivo .config, fica na raiz do código-fonte, é nele que fica toda a configuração do que o kernel saberá fazer quando for compilado. Cada linha segue a forma CONFIG_<opção>=<valor>, ao final, esse conjunto vira macros de pré-processador que o make transforma em código C condicional. Você não precisa se preocupar com isso, o utilitário make... criará esse arquivo para você (caso você não tenha).


Dentro do .config existe uma opção chamada config_local_version que você pode confundir o significado com EXTRAVERSION, abaixo vemos uma explicação:

  • EXTRAVERSION (Makefile)
    Fica no Makefile. É usado para identificar versões específicas do kernel base (como correções ou variações de empacotadores). Um exemplo com ele seria: 5.14.8-rev1. Afeta todos que usarem esse código-fonte.

  • CONFIG_LOCALVERSION (.conf)
    Fica dentro do arquivo .config. Adiciona um sufixo personalizado ao nome do kernel compilado. Mais indicado para personalizações locais, como quando você compila o kernel só para sua máquina. Pode ser usado junto do EXTRAVERSION. O resultado é seguinte (se o EXTRAVERSION for -rev1): 5.14.8-rev1-clicraze.


Use EXTRAVERSION se você mantém uma versão modificada do kernel para várias máquinas ou usuários ou use CONFIG_LOCALVERSION se quer personalizar localmente, sem alterar o Makefile principal. Vou configurar CONFIG_LOCALVERSION com o valor -clicraze.


Uma forma de pegar um .config já existente é pegando do Kernel que já temos instalado:

$ ls /boot/config-$(uname -r)
/boot/config-5.4.0-86-generic

# Podemos copiar esse arquivo para a pasta onde temos o código fonte do Kernel:
$ sudo cp /boot/config-$(uname -r) .config

# Agora importe esse arquivo e salve novamente:
$ make menuconfig
## Clique em 'Load', depois 'Save' e saia.

Dessa forma, ja teremos um .config pronto.


instalação extra

Como estou pegando o .config da Canonical, eu tive que instalar alguns pacotes a mais, seguem abaixo:

apt install -y dwarves


Compilando o Kernel


Agora vamos dar início ao processo de compilação do Kernel. Para que não tenha nenhum problema na compilaçãom você precisa de no mínimo 2GB de Ram e 20GB de espaço livre em disco.

# Se você ainda não tem o '.config' gere ele com algum dos comandos abaixo:
$ make config
$ make menuconfig
$ make xconfig
$ make gconfig
$ make nconfig

# Após termos criado ou obtido o '.config', basta usar o comando abaixo para compilar o Kernel.
#
# O -j(N) significa que vamos usar N núcleos da CPU,
# bzImage é o formato do arquivo final do Kernel.
#
# Esse processo pode demorar dependendo da configuração de Hardware, então pode esperar bastante!
# Levei 25 minutos usando a conf de 10 VCPU e 7GB de Ram.
$ sudo make -j10 bzImage

Se você obter o erro abaixo, edite o .config e deixe a opção CONFIG_SYSTEM_TRUSTED_KEYS em branco, ficando assim CONFIG_SYSTEM_TRUSTED_KEYS="". O valor padrão pede um certificado que não temos.

# Erro:
DESCEND objtool
CALL scripts/atomic/check-atomics.sh
CALL scripts/checksyscalls.sh
CHK include/generated/compile.h
make[1]: *** No rule to make target 'debian/canonical-certs.pem', needed by 'certs/x509_certificate_list'. Stop.
make[1]: *** Waiting for unfinished jobs....
make: *** [Makefile:1858: certs] Error 2
make: *** Waiting for unfinished jobs....

Casoa compilação tenha dado certo, você verá a saída abaixo, deixarei apenas o final:

  LZ4     arch/x86/boot/compressed/vmlinux.bin.lz4
MKPIGGY arch/x86/boot/compressed/piggy.S
AS arch/x86/boot/compressed/piggy.o
LD arch/x86/boot/compressed/vmlinux
ZOFFSET arch/x86/boot/zoffset.h
OBJCOPY arch/x86/boot/vmlinux.bin
AS arch/x86/boot/header.o
LD arch/x86/boot/setup.elf
OBJCOPY arch/x86/boot/setup.bin
BUILD arch/x86/boot/bzImage
Kernel: arch/x86/boot/bzImage is ready (#1)

Esse processo nos informa onde está a imagem do Kernel (arch/x86/boot/bzImage), esse arquivo é o que vemos em /boot com o nome de vmlinuz-*.



Compilando os Módulos para o Kernel


Agora vamos compilar os módulos, esses que estão em .config, nesse ponto os módulos serão Built-in ou Externos:

# Comece a conpilar os módulos, esse processo pode e vai demorar mais que o anterior, no meu caso demorou 32 minutos:
$ sudo make -j10 modules


Outras opções do MAKE


Existem outras opções do comando make que podemos usar, veja abaixo quais são:

  • make clean
    Usado para limpar a compilação que foi realizada, muito útil quando temos erro durante a compilação ou caso acabe o espaço em disco.

  • make mrproper
    Igual a opção acima, mas remove o .config.

  • make distclean
    Similar a opção mrproper, mas remove tudo que não veio com o código fonte (bakcups, dumps, temps e etc)

  • make localmodconfig
    Cria um .config baseado apenas nos módulos que seu sistema atual está carregando (lsmod).

  • make allnoconfig
    Cria um .config com tudo desativado (deixando apenas o necessário).

  • make localyesconfig
    Ativar no .config somente o que está em uso no momento do sistema (sem suporte a módulos).



Instalação dos Módulos


Agora devemos instalar o que compilamos, no caso, o Kernel e os módulos.


Para instalar o módulos siga o processo abaixo:

# Use o comando abaixo para instalar os módulos:
$ sudo make INSTALL_MOD_STRIP=1 modules_install

Esse comando irá instalar os módulos em /lib/modules com a versão do nosso Kernel. Esse argumento INSTALL_MOD_STRIP=1 fará com que os módulos sejam removidos após a instação, isso reduz drasticamente o tamanho do initrd.

# Liste os módulos instalados:
$ ls -ld /lib/modules/5.14.8-rev1-clicraze/
drwxr-xr-x 3 root root 4096 Jul 2 13:04 /lib/modules/5.14.8-rev1-clicraze/

Veja este link para tentar reduzir o tamanho do initrd, outra forma de reduzir o tamanho dele é usando um .config com menos recursos, já que o gerado automaticamente vem com bastante coisa.



Instalação do Kernel


Para instalar o Kernel devemos ter no mínimo 1.5GB livre, caso não tenha seguido a recomendação de redução acima dará erro durante a criação do novo initd, isso só acontece em ambientes onde o /boot está numa partição separada e/ou com pouco espaço de armazenamento.


Para instalar o Kernel, podemos fazer de duas formas:

  • Usando o make

    Siga os passos abaixo para instalar usando o comando make:

    $ sudo make install
    sh ./arch/x86/boot/install.sh \
    5.14.8-rev1-clicraze arch/x86/boot/bzImage \
    System.map "/boot"
    run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.14.8-rev1-clicraze /boot/vmlinuz-5.14.8-rev1-clicraze
    update-initramfs: Generating /boot/initrd.img-5.14.8-rev1-clicraze
    run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.14.8-rev1-clicraze /boot/vmlinuz-5.14.8-rev1-clicraze
    run-parts: executing /etc/kernel/postinst.d/update-notifier 5.14.8-rev1-clicraze /boot/vmlinuz-5.14.8-rev1-clicraze
    run-parts: executing /etc/kernel/postinst.d/xx-update-initrd-links 5.14.8-rev1-clicraze /boot/vmlinuz-5.14.8-rev1-clicraze
    I: /boot/vmlinuz.old is now a symlink to vmlinuz-5.4.0-216-generic
    I: /boot/initrd.img.old is now a symlink to initrd.img-5.4.0-216-generic
    I: /boot/vmlinuz is now a symlink to vmlinuz-5.14.8-rev1-clicraze
    I: /boot/initrd.img is now a symlink to initrd.img-5.14.8-rev1-clicraze
    run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.14.8-rev1-clicraze /boot/vmlinuz-5.14.8-rev1-clicraze
    Sourcing file `/etc/default/grub'
    Sourcing file `/etc/default/grub.d/init-select.cfg'
    Generating grub configuration file ...
    Found linux image: /boot/vmlinuz-5.14.8-rev1-clicraze
    Found initrd image: /boot/initrd.img-5.14.8-rev1-clicraze
    Found linux image: /boot/vmlinuz-5.4.0-216-generic
    Found initrd image: /boot/initrd.img-5.4.0-216-generic
    Found linux image: /boot/vmlinuz-5.4.0-169-generic
    Found initrd image: /boot/initrd.img-5.4.0-169-generic
    done

    # Agora reinicie e veja o novo Kernel:
    $ uname -r
    5.14.8-001-maddogs

  • Usando método manual

    Siga os passos abaixo para fazer essa instalação manualmente.

    # Instale o Kernel:
    $ sudo cp arch/x86/boot/bzImage /boot/vmlinuz-5.14.8-rev1-clicraze

    ############################################
    ### Veja o antigo apontamento do vmlinuz ###
    ############################################
    $ ls -lh /boot/vmlinuz
    lrwxrwxrwx 1 root root 24 Sep 23 21:11 /boot/vmlinuz -> vmlinuz-5.4.0-86-generic

    $ ls -lh /boot/vmlinuz.old
    lrwxrwxrwx 1 root root 24 Sep 23 21:11 /boot/vmlinuz.old -> vmlinuz-5.4.0-66-generic


    ## Agora apague o 'vmlinuz.old':
    $ sudo rm /boot/vmlinuz.old

    # Renomeie o atual 'vmlinuz' para 'vmlinuz.old':
    $ sudo mv /boot/vmlinuz /boot/vmlinuz.old

    # Crie o apontamento para o novo Kernel:
    $ cd /boot
    $ sudo ln -s vmlinuz-5.14.8-rev1-clicraze vmlinuz

    ## Agora vamos gerar um novo 'initrd' (5.14.8-rev1-clicraze é a versão que nomeamos):
    $ sudo mkinitramfs -o /boot/initrd.img-5.14.8-rev1-clicraze 5.14.8-rev1-clicraze

    ## Segue outro comando que podemos usar para gerar um 'initrd' (5.14.8-rev1-clicraze é a versão que nomeamos):
    $ sudo update-initramfs -c -k 5.14.8-rev1-clicraze

    # Agora atualize o grub:
    $ sudo update-grub
    Sourcing file `/etc/default/grub'
    Sourcing file `/etc/default/grub.d/init-select.cfg'
    Generating grub configuration file ...
    Found linux image: /boot/vmlinuz-5.14.8-rev1-clicraze
    Found initrd image: /boot/initrd.img-5.14.8-rev1-clicraze
    Found linux image: /boot/vmlinuz-5.4.0-86-generic
    Found initrd image: /boot/initrd.img-5.4.0-86-generic
    Found linux image: /boot/vmlinuz-5.4.0-66-generic
    Found initrd image: /boot/initrd.img-5.4.0-66-generic
    Found linux image: /boot/vmlinuz-5.4.0-42-generic
    Found initrd image: /boot/initrd.img-5.4.0-42-generic
    done

    # Agora reinicie e veja o novo Kernel ativo:
    $ uname -r
    5.14.8-rev1-clicraze

O initramfs originalmente é compactado com CPIO, mas em algumas distros também podemos encontrar ele compactado com gzip.



Initrd vs Initramfs


Ambos possuem o mesmo propósito, o initrd ou initramfs servem para dar suporte ao Kernel no momento da inicialização do sistema. É um filesystem temporário que é carregador na memória ram e não no disco, muitas vezes chamado de disco RAM inicial.


O initramfs ou initrd é um arquivo que contém um sistema de arquivos raiz temporário que é usado durante o processo de inicialização. O principal objetivo de um arquivo desses é fornecer os módulos necessários para que o Kernel possa acessar o sistema de arquivos raiz "verdadeiro" do sistema operacional.


Logo que o sistema de arquivos raiz fica disponível, o kernel monta todos os sistemas de arquivos configurados em /etc/fstab e, em seguida, executa o primeiro programa, um utilitário chamado init. O programa init é responsável por executar todos os scripts de inicialização e daemons do sistema. Depois que o programa init é carregado, o initramfs ou initrd é removido da RAM.


Coloquei sempre os dois para que você veja que ambos possuem o mesmo objetivo, porém, com limitações. O initramfs é o sistema usado nos dias de hoje, além de ser o sucessor do initrd.



ATENÇÃO

Mesmo mudando o tipo de arquitetura/conteúdo desses arquivos, você sempre verá com o nome de initrd, mesmo sendo um initramfs, em algumas distros (como o ArchLinux) podem colocar com initramfs e não mais como initrd.

  • initrd

    • Possui o tipo de sistema de arquivo sendo ramdev;

    • Possui a imagem de um FileSystem, por isso precisa de pelo menos um driver que tem que estar compilado em Kernel;

    • Um disco criado precisa ter um tamanho fixo;

    • É compactado com cpio e depois com gzip.

      # Verificando o tipo de arquivo:
      $ file initrd.image
      initrd.image: gzip compressed data, from Unix, last modified: Sun Aug 14 22:45:56 2016

      # Podemos descompactar e depois desagrupar com os comandos abaixo:
      $ zcat initrd.image | cpio -i
      106469 blocks

      # Possui a arquitetura:
      $ ls -lh | grep -v initrd.image
      total 20M
      drwxr-xr-x 2 vagrant vagrant 4.0K Oct 12 15:12 bin
      drwxr-xr-x 3 vagrant vagrant 4.0K Oct 12 15:12 conf
      drwxr-xr-x 8 vagrant vagrant 4.0K Oct 12 15:12 etc
      -rwxr-xr-x 1 vagrant vagrant 6.6K Oct 12 15:12 init
      drwxr-xr-x 7 vagrant vagrant 4.0K Oct 12 15:12 lib
      drwxr-xr-x 2 vagrant vagrant 4.0K Oct 12 15:12 lib64
      drwxr-xr-x 2 vagrant vagrant 4.0K Oct 12 15:12 run
      drwxr-xr-x 2 vagrant vagrant 4.0K Oct 12 15:12 sbin
      drwxr-xr-x 8 vagrant vagrant 4.0K Oct 12 15:12 scripts
      drwxr-xr-x 3 vagrant vagrant 4.0K Oct 12 15:12 var
      # Realmente sendo um filesystem completo.

  • initramfs

    • Possui o tipo de sistema de arquivo sendo tmpfs;

    • O tmpfs não precisa de um driver porque está sempre no Kernel;

    • É um arquivo agrupado com CPIO, mas em algumas distros também podemos encontrar ele compactado com gzip.

      # Verificando o tipo de arquivo:
      $ file initrd.img
      initrd.img: ASCII cpio archive (SVR4 with no CRC)

      # Podemos desagrupar com o comando abaixo (quando é CPIO):
      $ sudo cpio -i < initrd.img
      62 blocks

      # Possui uma arquitetura assim:
      $ tree
      .
      ├── initrd.img
      └── kernel
      └── x86
      └── microcode
      └── AuthenticAMD.bin

      3 directories, 2 files


Criação de um pacote de instalação do Kernel


Com a compilação em mãos, podemos criar um pacote para facilitar a instalação dele em outras máquinas, para isso, veja abaixo:

# Criando um pacote .deb do Kernel:
$ sudo make deb-pkg


## Criando um pacote .rpm do Kernel:
$ sudo make rpm-pkg

## Criando um pacote .rpm somente com a imagem do Kernel:
$ sudo make binrpm-pkg

Os pacotes ficarão em /usr/src.


PacotesDescrição
*.descUsado para realizar o checksum.
*.orig.tar.gzVersão original do Kernel (código fonte).
*headers*Cabeçalhos para o novo Kernel.
*image*Imagem do Kernel.
*libc-devCabeçalhos das bibliotecas.
*amd64.debPacote do Kernel que vamos usar para instalar em outras máquinas.


DKMS


O Dynamic Kernel Module Support (DKMS) é um programa/framework que nos permite gerar módulos para o kernel do Linux, onde as fontes não residam dentro da árvore principal de fontes, ou seja, cujo as fontes que vão gerar esse módulo não façam parte das fontes do Kernel em sí. O conceito aqui é poder ter alguns módulos automaticamente reconstruídos quando uma nova versão do kernel é instalada.


Um exemplo para isso são os módulos da NVIDIA (pelo menos no ArchLinux) e o DroidCam que devemos sempre construir novos módulos toda vez que um novo Kernel é instalado; onde esse processo de reconstruir um novo módulo para o Kernel novo é completamente manual.


Com o DKMS a reconstrução é automática ao instalar um novo Kernel.

Dependendo do pacote, ele pode vir pronto para trabalhar com o DKMS, como em package_name-dkms, nesse caso basta instalar e já temos o suporte ao DKMS nesse pacote ou pode não existir uma versão para isso, e vamos ter que adicionar esse pacote ao DKMS manualmente.

Instale o dkms:

$ sudo apt install dkms 

Vejamos algumas opções do DKMS:

# Listando o status:
$› dkms status
nvidia, 460.91.03, 5.4.0-80-generic, x86_64: installed
nvidia, 460.91.03, 5.4.0-81-generic, x86_64: installed
nvidia, 460.91.03, 5.4.0-84-generic, x86_64: installed
nvidia, 460.91.03, 5.4.0-86-generic, x86_64: installed
nvidia, 460.91.03, 5.4.0-88-generic, x86_64: installed
virtualbox, 6.1.26, 5.4.0-81-generic, x86_64: installed
virtualbox, 6.1.26, 5.4.0-84-generic, x86_64: installed
virtualbox, 6.1.26, 5.4.0-86-generic, x86_64: installed
virtualbox, 6.1.26, 5.4.0-88-generic, x86_64: installed

Para que isso funcione, é instalado em /usr/src o código fonte do programa que queremos habilitar o suporte do DKMS, com o arquivo de configuração do DKMS: /usr/src/nvidia-460.91.03/dkms.conf.

# listando o conteúdo:
$ cat /usr/src/nvidia-460.91.03/dkms.conf
PACKAGE_NAME="nvidia"
PACKAGE_VERSION="460.91.03"
CLEAN="make clean"
BUILT_MODULE_NAME[0]="nvidia"
DEST_MODULE_LOCATION[0]="/kernel/drivers/char/drm"
PROCS_NUM=`nproc`
[ $PROCS_NUM -gt 16 ] && PROCS_NUM=16
MAKE[0]="unset ARCH; [ ! -h /usr/bin/cc ] && export CC=/usr/bin/gcc; env NV_VERBOSE=1 \
'make' -j$PROCS_NUM NV_EXCLUDE_BUILD_MODULES='' KERNEL_UNAME=${kernelver} IGNORE_XEN_PRESENCE=1 IGNORE_CC_MISMATCH=1 SYSSRC=$kernel_source_dir LD=/usr/bin/ld.bfd modules"
BUILT_MODULE_NAME[1]="nvidia-modeset"
DEST_MODULE_LOCATION[1]="/kernel/drivers/char/drm"
BUILT_MODULE_NAME[2]="nvidia-drm"
DEST_MODULE_LOCATION[2]="/kernel/drivers/char/drm"
AUTOINSTALL="yes"
PATCH[0]="disable_fstack-clash-protection_fcf-protection.patch"
#PATCH[1]="buildfix_kernel_5.6.patch"
#PATCH_MATCH[0]="^4.[6-7]"
BUILT_MODULE_NAME[3]="nvidia-uvm"
DEST_MODULE_LOCATION[3]="/kernel/drivers/char/drm"
#PATCH[2]="buildfix_kernel_4.9_amd64_only.patch"


Dracut


O Dracut é usado para gerar uma imagem initramfs em ambientes Redhat. Similiar ao update-initramfs (que roda em Debian Like), mas o Dracut roda em sistemas RedHat.

Antigamente se usava o mkinitrd no ambiente Redhat, mas hoje foi substituído pelo Dracut.