Próximo: , Anterior: , Acima: Configuração do sistema   [Conteúdo][Índice]


3.2 Customizando o Kernel

Guix é, em sua essência, uma distribuição baseada em código-fonte com substitutos (veja Substitutos em GNU Guix Reference Manual) e, como tal, construir pacotes a partir de seu código-fonte é uma parte esperada das instalações e atualizações regulares de pacotes. Dado este ponto de partida, faz sentido que sejam feitos esforços para reduzir a quantidade de tempo gasto na compilação de pacotes, e as recentes mudanças e atualizações na construção e distribuição de substitutos continuam a ser um tópico de discussão dentro do Guix.

O kernel, embora não exija uma superabundância de RAM para ser construído, leva muito tempo em uma máquina média. A configuração oficial do kernel, como é o caso de muitas distribuições GNU/Linux, erra pelo lado da inclusão, e é isso que realmente faz com que a construção demore tanto tempo quando o kernel é compilado a partir do código-fonte.

O kernel do Linux, entretanto, também pode ser descrito apenas como um pacote antigo normal e, como tal, pode ser personalizado como qualquer outro pacote. O procedimento é um pouco diferente, embora isso se deva principalmente à natureza de como a definição do pacote é escrita.

A definição do pacote do kernel linux-libre é na verdade um procedimento que cria um pacote.

(define* (make-linux-libre* version gnu-revision source supported-systems
                            #:key
                            (extra-version #f)
                            ;; A function that takes an arch and a variant.
                            ;; See kernel-config for an example.
                            (configuration-file #f)
                            (defconfig "defconfig")
                            (extra-options (default-extra-linux-options version)))
  ...)

O pacote linux-libre atual é para a série 5.15.x e é declarado assim:

(define-public linux-libre-5.15
  (make-linux-libre* linux-libre-5.15-version
                     linux-libre-5.15-gnu-revision
                     linux-libre-5.15-source
                     '("x86_64-linux" "i686-linux" "armhf-linux"
                       "aarch64-linux" "riscv64-linux")
                     #:configuration-file kernel-config))

Quaisquer chaves às quais não sejam atribuídos valores herdam seu valor padrão da definição make-linux-libre. Ao comparar os dois trechos acima, observe o comentário do código que se refere a #:configuration-file. Por causa disso, não é realmente fácil incluir uma configuração de kernel personalizada na definição, mas não se preocupe, existem outras maneiras de trabalhar com o que temos.

Existem duas maneiras de criar um kernel com uma configuração de kernel personalizada. A primeira é fornecer um arquivo .config padrão durante o processo de construção, incluindo um arquivo .config real como uma entrada nativa para nosso kernel personalizado. A seguir está um trecho da fase 'configure personalizada da definição do pacote make-linux-libre:

(let ((build  (assoc-ref %standard-phases 'build))
      (config (assoc-ref (or native-inputs inputs) "kconfig")))

  ;; Use a custom kernel configuration file or a default
  ;; configuration file.
  (if config
      (begin
        (copy-file config ".config")
        (chmod ".config" #o666))
      (invoke "make" ,defconfig)))

Abaixo está um exemplo de pacote de kernel. O pacote linux-libre não é nada especial e pode ser herdado e ter seus campos substituídos como qualquer outro pacote:

(define-public linux-libre/E2140
  (package
    (inherit linux-libre)
    (native-inputs
     `(("kconfig" ,(local-file "E2140.config"))
      ,@(alist-delete "kconfig"
                      (package-native-inputs linux-libre))))))

No mesmo diretório do arquivo que define linux-libre-E2140 está um arquivo chamado E2140.config, que é um arquivo de configuração real do kernel. A palavra-chave defconfig de make-linux-libre é deixada em branco aqui, então a única configuração do kernel no pacote é aquela que foi incluída no campo native-inputs.

A segunda maneira de criar um kernel customizado é passar um novo valor para a palavra-chave extra-options do procedimento make-linux-libre. A palavra-chave extra-options funciona com outra função definida logo abaixo dela:

(define (default-extra-linux-options version)
  `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true)
   ;; Modules required for initrd:
   ("CONFIG_NET_9P" . m)
   ("CONFIG_NET_9P_VIRTIO" . m)
   ("CONFIG_VIRTIO_BLK" . m)
   ("CONFIG_VIRTIO_NET" . m)
   ("CONFIG_VIRTIO_PCI" . m)
   ("CONFIG_VIRTIO_BALLOON" . m)
   ("CONFIG_VIRTIO_MMIO" . m)
   ("CONFIG_FUSE_FS" . m)
   ("CONFIG_CIFS" . m)
   ("CONFIG_9P_FS" . m)))

(define (config->string options)
  (string-join (map (match-lambda
                      ((option . 'm)
                       (string-append option "=m"))
                      ((option . #true)
                       (string-append option "=y"))
                      ((option . #false)
                       (string-append option "=n")))
                    options)
               "\n"))

E no script de configuração personalizado do pacote ‘make-linux-libre‘:

;; Appending works even when the option wasn't in the
;; file.  The last one prevails if duplicated.
(let ((port (open-file ".config" "a"))
      (extra-configuration ,(config->string extra-options)))
  (display extra-configuration port)
  (close-port port))

(invoke "make" "oldconfig")

Portanto, ao não fornecer um arquivo de configuração, o .config começa em branco e então escrevemos nele a coleção de flags que desejamos. Aqui está outro kernel personalizado:

(define %macbook41-full-config
  (append %macbook41-config-options
          %file-systems
          %efi-support
          %emulation
          ((@@ (gnu packages linux) default-extra-linux-options) version)))

(define-public linux-libre-macbook41
  ;; XXX: Access the internal 'make-linux-libre*' procedure, which is
  ;; private and unexported, and is liable to change in the future.
  ((@@ (gnu packages linux) make-linux-libre*)
   (@@ (gnu packages linux) linux-libre-version)
   (@@ (gnu packages linux) linux-libre-gnu-revision)
   (@@ (gnu packages linux) linux-libre-source)
   '("x86_64-linux")
   #:extra-version "macbook41"
   #:extra-options %macbook41-config-options))

In the above example %file-systems is a collection of flags enabling different file system support, %efi-support enables EFI support and %emulation enables a x86_64-linux machine to act in 32-bit mode also. The default-extra-linux-options procedure is the one defined above, which had to be used to avoid loosing the default configuration options of the extra-options keyword.

Tudo isso parece viável, mas como saber quais módulos são necessários para um sistema específico? Dois lugares que podem ser úteis para tentar responder a esta pergunta são o Gentoo Handbook e o documentação do próprio kernel. Pela documentação do kernel, parece que make localmodconfig é o comando que queremos.

Para realmente executar make localmodconfig primeiro precisamos obter e descompactar o código-fonte do kernel:

tar xf $(guix build linux-libre --source)

Uma vez dentro do diretório que contém o código-fonte, execute touch .config para criar um .config inicial e vazio para começar. make localmodconfig funciona vendo o que você já tem em .config e informando o que está faltando. Se o arquivo estiver em branco, você está perdendo tudo. O próximo passo é executar:

guix shell -D linux-libre -- make localmodconfig

e observe a saída. Observe que o arquivo .config ainda está vazio. A saída geralmente contém dois tipos de avisos. O primeiro começa com "WARNING" e pode ser ignorado no nosso caso. A segunda leitura:

module pcspkr did not have configs CONFIG_INPUT_PCSPKR

Para cada uma dessas linhas, copie a parte CONFIG_XXXX_XXXX para .config no diretório e anexe =m, para que no final fique assim:

CONFIG_INPUT_PCSPKR=m
CONFIG_VIRTIO=m

Após copiar todas as opções de configuração, execute make localmodconfig novamente para ter certeza de que você não tem nenhuma saída começando com “module”. Depois de todos esses módulos específicos da máquina, restam mais alguns que também são necessários. CONFIG_MODULES é necessário para que você possa construir e carregar módulos separadamente e não ter tudo embutido no kernel. CONFIG_BLK_DEV_SD é necessário para leitura de discos rígidos. É possível que existam outros módulos dos quais você precisará.

Este post não pretende ser um guia para configurar seu próprio kernel, portanto, se você decidir construir um kernel personalizado, você terá que procurar outros guias para criar um kernel adequado às suas necessidades.

A segunda maneira de definir a configuração do kernel faz mais uso dos recursos do Guix e permite compartilhar segmentos de configuração entre diferentes kernels. Por exemplo, todas as máquinas que usam EFI para inicializar possuem vários sinalizadores de configuração EFI necessários. É provável que todos os kernels compartilhem uma lista de sistemas de arquivos para suporte. Ao usar variáveis, é mais fácil ver rapidamente quais recursos estão habilitados e garantir que você não tenha recursos em um kernel, mas ausentes em outro.

No entanto, não foi discutido o initrd do Guix e sua personalização. É provável que você precise modificar o initrd em uma máquina usando um kernel customizado, já que certos módulos que devem ser compilados podem não estar disponíveis para inclusão no initrd.


Próximo: API de imagem do sistema Guix, Anterior: Login automático em um TTY específico, Acima: Configuração do sistema   [Conteúdo][Índice]