Linuxカーネルはどれくらい小さくできますか?

少し前に、ubuntu20.04からgentooに仮想マシンをOracleCloud変換する方法学びました常に無料の階層内で提供されるマシンは非常に脆弱です。これは、特に、カーネルの再コンパイルがかなり長いプロセスに変わるという事実につながります。元のubuntu20.04カーネルでは、構成に7904パラメーターが含まれていました。私がした後:



make localmodconfig && make localyesconfig
      
      





パラメータの数は1285に減少しました。カーネルから不要なものをすべて捨てて、何が起こるかを確認するのは興味深いことでした。



バニラカーネル5.4.0をコンパイルします。これは、私のgentooインストールで使用されているバージョンだからです。プロセスを高速化するために、作業マシン(i7、8コア、64Gb RAM、tmpfs)でカーネルをコンパイルします。完成したカーネルをOracleCloudのマシンにコピーします。次のコマンドでプロセスを開始する必要があります。



make tinyconfig
      
      





これにより、現在のアーキテクチャの最小コアの.configファイルが提供されます。私の場合、このファイルにはコメントではない284行の空白以外の行が含まれています。



それをコンパイルして、カーネルサイズを見てみましょう:



$ 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
$

      
      





このカーネルは完全に役に立たない。起動できないだけでなく、問題を報告する機能もありません。これを修正しましょう。パラメータをアクティブにするには、次のコマンドを使用します。



script/config -e config_parameter_name
      
      





したがって、カーネルは64ビットになり、カーネル診断出力をアクティブにし、ターミナルサポートを有効にし、シリアルポートとそのコンソールを構成します。



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





Oracle Cloudのマシンは、このカーネルで起動できず、コンソールへの出力はありません。結局のところ、依存関係であるEFIとACPIのサポートを追加する必要があります。スクリプト./scripts/configは、逆依存関係を追加するためのロジックを実装していません。CONFIG_EFIのみを追加すると、makeはこのパラメーターを構成から削除します。オプションを有効にすると、以下のオプションが含まれることが多いことにも注意してください。したがって、CONFIG_ACPIを有効にする場合、たとえば、オン/オフボタンのサポートなど、自動的に有効になります。



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





コアをまとめる:



$ 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
$
      
      





このカーネルはまだブートプロセスを完了できませんが、少なくともそれを報告することはできます。



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. ]---
      
      





必要なパラメータを追加しましょう:



# 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
      
      





コアをまとめる:

$ 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
$
      
      





そして、私たちはロードされます。今回は、カーネルがルートディスクを正常に検出しましたが、コンソールにエラーが表示されます。



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





ログインしようとしています:

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





また、機能しませんが、どのパラメーターを追加するかを明確に尋ねられます。それと他の必要なパラメータを追加します:



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





コアをまとめる:



$ 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
$
      
      





今回はなんとかログインできます:



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:~#
      
      





やったー!Sshも機能します。それにもかかわらず、コンソールに再びエラーがあります。



 * 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

      
      





また、dmesgには次のものもあります。



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





リアルタイムクロック、vfatファイルシステム、およびinotifyのサポートを追加します。



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





コアをまとめる:



$ 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
$
      
      





うーん、vfatドライブはまだマウントできません:



 * Some local filesystem failed to mount
      
      





そして、dmesgでもう1つのエラーが発生する理由は次のとおりです。



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





パラメータを追加します。



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





コアをまとめる:



$ 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
$
      
      





ロードしました。コンソールにエラーはありませんが、dmesgに新しいエラーが表示されました。



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





修正:



./scripts/config -e CONFIG_EPOLL
      
      





コアをまとめる:



$ 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
$
      
      





再起動すると、今回は新しいエラーは表示されません。



私の作業マシン(i7、8コア、64 GB RAM、tmpfs)では、最終的な構成は1分16秒で構築されます。 2つのコアを備えた通常のディスク上のOracleCloudでは、同じプロセスに19分51秒かかります。



結果として得られるカーネルは、完全に最小ではありません。したがって、たとえば、ネットワークサポートを有効にすると、さまざまなネットワークアダプタが追加されます。私は完璧主義に従事せず、必要のないものすべてを完全に一掃しました。さらに、ロードとクイックテストでは、追加の重要なカーネルコンポーネントがないことによる問題は明らかになりませんでしたが、それらはおそらく存在することを警告したいと思います。だから突然あなたが私の設定を再利用することにした場合 特定のケースについてカーネルを徹底的にテストし、必要に応じて必要なカーネルパラメータを追加してください。



All Articles