Quelle peut être la taille d'un noyau Linux?

Il y a quelque temps, j'ai appris à convertir des machines virtuelles en cloud oracle d'ubuntu 20.04 en gentoo. Les machines fournies dans le niveau toujours gratuit sont très faibles. Ceci, en particulier, conduit au fait que la recompilation du noyau se transforme en un processus assez long. Le noyau ubuntu 20.04 d'origine avait 7904 paramètres dans sa configuration. Après avoir fait:



make localmodconfig && make localyesconfig
      
      





le nombre de paramètres est tombé à 1285. Il est devenu intéressant pour moi d'essayer de supprimer toutes les choses inutiles du noyau et de voir ce qui se passe.



Je compilerai le noyau vanilla 5.4.0 car c'est la version utilisée sur mon installation gentoo. Pour accélérer le processus, je compile le noyau sur ma machine de travail (i7, 8 cœurs, 64 Go de RAM, tmpfs). Je copie le noyau fini sur la machine dans Oracle Cloud. Vous devez démarrer le processus avec la commande:



make tinyconfig
      
      





Cela vous donnera un fichier .config pour le noyau minimum de l'architecture actuelle. Dans mon cas, ce fichier contient 284 lignes non vides qui ne sont pas des commentaires.



Compilons-le et regardons la taille du noyau:



$ yes ""|make -j$(nproc)
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 441872 Jan 31 18:09 arch/x86/boot/bzImage
284
$

      
      





Ce noyau est complètement inutile. Non seulement il ne peut pas démarrer, mais il n'a même pas la capacité de signaler les problèmes. Corrigeons ça. Pour activer les paramètres, j'utiliserai la commande:



script/config -e config_parameter_name
      
      





Donc, notre noyau sera 64 bits, nous activons la sortie de diagnostic du noyau, activons le support du terminal, configurons le port série et la console dessus:



./scripts/config -e CONFIG_64BIT -e CONFIG_PRINTK -e CONFIG_TTY -e CONFIG_SERIAL_8250 -e CONFIG_SERIAL_8250_CONSOLE
      
      





Une machine dans Oracle Cloud ne pourra pas démarrer avec ce noyau, il n'y aura pas de sortie vers la console. Il s'est avéré que vous devez ajouter la prise en charge d'EFI et ACPI, qui est sa dépendance. Le script ./scripts/config n'implémente pas la logique d'ajout de dépendances inverses, c'est-à-dire si vous n'ajoutez que CONFIG_EFI, alors make supprimera ce paramètre de la configuration. Il convient également de noter que l'activation des options comprend souvent les options ci-dessous. Ainsi, dans le cas de l'activation de CONFIG_ACPI, il est automatiquement activé, par exemple, la prise en charge du bouton marche / arrêt.



./scripts/config -e CONFIG_ACPI -e CONFIG_EFI -e CONFIG_EFI_STUB
      
      





Rassembler le noyau:



$ yes ""|make -j$(nproc)
$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1036960 Jan 31 18:13 arch/x86/boot/bzImage
409
$
      
      





Ce noyau ne peut toujours pas terminer le processus de démarrage, mais il est au moins capable de le signaler:



Kernel panic - not syncing: No working init found.  Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance.
Kernel Offset: 0x22000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
---[ end Kernel panic - not syncing: No working init found.  Try passing init= option to kernel. See Linux Documentation/admin-guide/init.rst for guidance. ]---
      
      





Ajoutons les paramètres requis:



# virtual guest support and pci
./scripts/config -e CONFIG_PCI -e CONFIG_VIRTIO_PCI -e CONFIG_VIRTIO -e CONFIG_VIRTIO_MENU -e CONFIG_PARAVIRT -e CONFIG_HYPERVISOR_GUEST  
# disk support
./scripts/config -e CONFIG_BLOCK -e CONFIG_SCSI -e CONFIG_BLK_DEV_SD -e CONFIG_SCSI_VIRTIO
# filesystems
./scripts/config -e CONFIG_EXT4_FS -e CONFIG_PROC_FS -e CONFIG_SYSFS -e CONFIG_DEVTMPFS -e CONFIG_DEVTMPFS_MOUNT
# executable formats
./scripts/config -e CONFIG_BINFMT_ELF -e CONFIG_BINFMT_SCRIPT
# network
./scripts/config -e CONFIG_NET -e CONFIG_VIRTIO_NET -e CONFIG_PACKET -e CONFIG_UNIX -e CONFIG_INET -e CONFIG_NET_CORE -e CONFIG_NETDEVICES -e CONFIG_VIRTIO_NET
      
      





Rassembler le noyau:

$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1950368 Jan 31 18:18 arch/x86/boot/bzImage
616
$
      
      





Et nous sommes chargés. Cette fois, le noyau trouve avec succès le disque racine, mais nous voyons des erreurs dans la console:



The futex facility returned an unexpected error code.
...
 * Call to flock failed: Function not implemented
      
      





Nous essayons de nous connecter:

(none) login: root
process 182 (login) attempted a POSIX timer syscall while CONFIG_POSIX_TIMERS is not set
Password:
setgid: Function not implemented
      
      





Cela ne fonctionne pas non plus, mais on nous demande sans ambiguïté quel paramètre ajouter. Ajoutez-le et d'autres paramètres nécessaires:



./scripts/config -e CONFIG_POSIX_TIMERS -e CONFIG_FUTEX -e CONFIG_FILE_LOCKING -e CONFIG_MULTIUSER
      
      





Rassembler le noyau:



$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 1979040 Jan 31 18:25 arch/x86/boot/bzImage
623
$
      
      





Cette fois, nous parvenons à nous connecter:



instance-20210124-1735 login: root
Password:
Last login: Mon Feb  1 02:25:10 UTC 2021 from 73.239.106.74 on ssh
root@instance-20210124-1735:~#
      
      





Hourra! Ssh fonctionne aussi. Néanmoins, il y a à nouveau des erreurs dans la console:



 * Some local filesystem failed to mount
...
hwclock: Cannot access the Hardware Clock via any known method.
hwclock: Use the --verbose option to see the details of our search for an access method.
 * Failed to set the system clock

      
      





Et dans dmesg on trouve aussi:



[    2.910198] udevd[360]: inotify_init failed: Function not implemented
      
      





Nous ajoutons la prise en charge de l'horloge en temps réel, du système de fichiers vfat et de inotify:



./scripts/config -e CONFIG_RTC_CLASS -e CONFIG_DNOTIFY -e CONFIG_INOTIFY_USER -e CONFIG_VFAT_FS
      
      





Rassembler le noyau:



$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:36 arch/x86/boot/bzImage
643
$
      
      





Hmmm, le lecteur vfat ne peut toujours pas monter:



 * Some local filesystem failed to mount
      
      





Et voici la réponse pourquoi dans dmesg avec une autre erreur:



[    3.782884] udevd[527]: error creating signalfd
[    4.107698] FAT-fs (sda15): codepage cp437 not found
      
      





Ajouter des paramètres:



./scripts/config -e CONFIG_SIGNALFD -e CONFIG_NLS_CODEPAGE_437 -e CONFIG_NLS_ISO8859_1
      
      





Rassembler le noyau:



$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2015904 Jan 31 18:41 arch/x86/boot/bzImage
646
$
      
      





On charge, il n'y a pas d'erreurs dans la console, mais une nouvelle erreur est apparue dans dmesg:



[    2.756136] udevd[360]: error creating epoll fd: Function not implemented
      
      





Nous fixons:



./scripts/config -e CONFIG_EPOLL
      
      





Rassembler le noyau:



$ ll arch/x86/boot/bzImage && grep -v ^# .config|grep -c .
-rw-rw-r-- 1 kvt kvt 2020000 Jan 31 19:13 arch/x86/boot/bzImage
647
$
      
      





Nous redémarrons et cette fois nous ne voyons aucune nouvelle erreur!



Sur ma machine de travail (i7, 8 cœurs, 64 Go de RAM, tmpfs), la configuration finale est construite en 1m 16s. Dans le cloud oracle avec deux cœurs et sur un disque normal, le même processus prend 19m 51s.



Le noyau résultant n'est pas absolument minimal. Ainsi, par exemple, l'activation de la prise en charge réseau ajoute un tas d'adaptateurs réseau différents. Je ne me suis pas engagé dans le perfectionnisme et j'ai nettoyé absolument tout ce qui n'est pas nécessaire. De plus, je tiens à vous avertir que bien que le chargement et les tests rapides n'aient pas révélé de problèmes liés à l'absence de composants supplémentaires importants du noyau, ils existent très probablement. Donc si du coup vous décidez de réutiliser ma config veuillez tester soigneusement le noyau pour votre cas particulier et ajouter les paramètres de noyau requis si nécessaire.



All Articles