4 Aralık 2021 Cumartesi

Linux Kernel'ini Vmware için Derlemek


Merhaba. Bu yazıda linux kernel (çekirdek) derleme hakkında genel bilgiler verip, karşılaştığım bir sorunun çözümünü ele alacağım. Bu aslında sonraki yazının bir bölümü olacaktı, ama sorun o kadar uğraştırdı ki, ayrı bir yazıda ele almaya değeceğini düşündüm. Başlık zaten sonraki yazı hakkında ipucu verecektir.


Linux'ta Kernel Derlemek

Kernel derlemek, özel bir cihazla çalışmıyorsanız (örn. gömülü (embedded) sistem veya standart kernel'ın desteklemediği çok yeni bir donanımla) veya LFS gibi deneysel veya Gentoo gibi kernel'ın derlenmiş olarak gelmediği bir dağıtım kullanmadıkça, gündelik kullanımda yapılması gereken birşey değil. Öte yandan, öğrenmek veya sisteme en düşük seviyede hakim olmak için bence bilinmesi mutlak gerekli. Zaten bir kaç tane önkoşulu yerine getirip, temelleri bildikten sonra, herhangi bir kaynak kodu derlemekten daha kolay.

Ben bu yazıda kernel v5.13.12'yi derleyeceğim. İhtiyacım olan öncelikle kaynak kod. Bu arada kernel sürümünün önemli olduğu tek yer .config dosyası, buna da ileriki paragraflarda değineceğim. Tüm kernel'lar www.kernel.org/pub adresinde linux/kernel alt dizininden ulaşılabilir. Daha küçük olduğu için yukarıda .xz dosyanın bağlantısını verdim ama aynı dosyanın .gz sürümü de bulunabilir.

Bu dosyayı indirip açtım. Elbette bir dosyayı derlemek için make, gcc ve gcc-c++ gibi olması zorunlu programlar makinamda zaten yüklüydü. Eksik olan tek paket ncurses-devel'di. Bu aslında zorunlu değil, make menuconfig için gerekli ama menuconfig, kernel özelliklerini seçerken kolaylık sağlıyor. kernel'in bağımlılıkları bunlarla sınırlı değil, v5.13 sürümü için ayrıntılı liste kernel.org dökümantasyonunda var. Ama listedeki tüm paketlerin yüklü olması zorunlu değil, örn. PPP'yle ilgili birşey derlemeyecekseniz, pppd'ye gerek yok veya OpenSSL yalnız kernel modülleri imzalanacaksa gerekli.

Derlemeye geçmeden önce bazı ön bilgiler: make clean bilindiği gibi derlenen dosyaları silip kodu baştan derlemeye hazır hale getirir. linux'a özgü make mrproper ise .config dosyasını ve diğer ayarları da siler [1]. Bu yüzden ben de başlamadan önce bu komutla dizini temizledim ve sonra make defconfig ile en standart ayarları aktifleştirdim. Sözünü ettiğim bu ayarlar .config dosyasında tutuluyor, dolayısıyla defconfig aslında standart .config dosyası oluşturuyor. Bu ayarlar bir metin düzenleyiciyle görülebilir veya make menuconfig komutuyla, ncurses TUI kullanarak düzenlenebilir. .config dosyasında 4845 satır olduğundan tüm ayarları bu dosyadan elle yapmak hiç mantıklı değil.

.config dosyası her kernel sürümü için farklıdır, çünkü her minör sürümde bir kaç özellik eklenir veya çıkarılır. Haliyle, o sürüme uyumlu olmayan bir .config dosyası kullanarak derleyemem. Ama daha eski bir kernel'a ait .config dosyasını, yeni kernel'a make oldconfig komutuyla uyarlayabilirim. Bu komut, kullanıcıya yalnız .config'de olmayan (o kernel'a yeni eklenmiş) seçenekleri sorar. Tabi ki eski .config derken, v2.6 config'ini v5.13'e uyarlamak pek mantıklı iş değil.

make menuconfig metin arayüzü

make menuconfig komutunu çalıştırdım ve yukarıdaki menü çıktı. Ana menüdeki "--->" işaretli satırlar bir alt menüyü gösteriyor. Bu menüdeki tüm satırlar (eğer bir alt menüsü yoksa) .config'deki bir satıra karşılık geliyor. Kernel belgelerinde, açılması gereken özellikler yanında [*] ve açılmaması gerekenler yanında [ ] işaretiyle veriliyor. [M] ise özelliğin modüler olduğu anlamına geliyor, bunu daha sonra açıklayacağım. Örn. aşağıdaki görselde LFS'i systemd ile çalıştırmak için gereken kernel seçenekleri verilmiş:

LFS systemd kernel seçenekleri


Örneğin "Auditing Support", "Control Group support" ve "Configure standard kernel ..." gibi özellikler "General setup" altında; "open by fhandle syscalls" ise "Configure standard kernel ..."ın altında. Satır sonunda kareli parantez içinde verilen adlar, özelliğin .config içindeki maddesi (item). Bu arada, "Processor type and features" altında olması gereken "Enable seccomp ..."u bulamadım (kaynak hatalı). Bu özellik, Kernelconfig.io'ya göre v5.13'te "General architecture-dependent options" altında, ama eski sürümlerde mesela v5.9.9'da "Processor type and features" altında. Bu maddeler, menuconfig'deyken '/'a basıp, adlarıyla aratılabilir. Ancak ben menuconfig'den değil, .config dosyasından da bu ayarı değiştirebilirim (aşağıda). Bu arada özelliklerin genelde (her zaman değil) ilk harfi, aynı zamanda onun klavye kısa yolu, yani "Processor type..."a gidip "E" ye basarak, "E" ile başlayıp o an ekranda görünen seçenekler arasında gezebilirim.

$ grep -n SECCOMP .config
687:CONFIG_HAVE_ARCH_SECCOMP=y
688:CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
689:CONFIG_SECCOMP=y
690:CONFIG_SECCOMP_FILTER=y
691:# CONFIG_SECCOMP_CACHE_DEBUG is not set

Bu değer 689. satırda zaten açılmış. Gerekirse 'y'yi 'n' yapıp kapabilirim. Tüm bu özellikler .config dosyasında var. Sözünü ettiğim [M] içinse aşağıda bir örnek var:

BLFS: LVM için kernel seçenekleri


Bazı kernel seçeneklerinde bulunan M, özelliğin kernel modülü olarak derlenmesi anlamına geliyor. Bütün kernel fonksiyonları, /boot dizininde derlenmiş durumda bulunan vmlinuz-... adlı kernel dosyasında bulunmak zorunda değildir. Bu dosyayı olabildiğince küçük tutmak için, bazı fonksiyonlar modül olarak /usr/lib/modules altında tutulur, ve yalnız ihtiyaç olursa yüklenir. Bu sayede, örn. LVM diski olmayan bir makinada LVM modüllerinin veya ses kartı olmayan bir sanal makinada ses kartına ait modüllerin boşuna bellekte tutulması gerekmez.

Modül dosyaları .ko (kernel object) uzantılı dosyalardır. insmod veya modprobe ile yüklenir, lsmod'la listelenirler. Modüller, kernel'a sonradan eklenecek işlevlerin, kernel'ı tekrar derlemeye gerek kalmadan kullanılmasını sağlar [2]. Modüllere ait ayarlar /etc/modprobe.d/ dizinindeki .conf dosyalarında tutulur. Bu dosyalarla modüllere parametre girilebilir veya yüklenmesi engellenebilir. Kernel modülleri burada ele alabileceğimden çok daha geniş bir konu.

menuconfig yardımıyla veya elle istediğim seçenekleri ayarladıktan sonra make diyip yeni kernel'ı derledim. Tabii ki bu anında olmuyor. Benim bilgisayarımda standart seçeneklerle derlemek, yaklaşık 5dk sürüyor. Bazı seçenekler standartta modül olarak derlendiğinden, make'ten sonra make modules_install ile bu dosyaların o kernel'a karşılık gelen modül dizinine kopyalanması gerekiyor.

Derleme bittikten sonra, arch/x86/boot/bzImage (kernel) dosyası /boot altına vmlinuz-... adıyla kopyalanabilir ve grub yardımıyla açılabilir. Bu arada her dağıtım kernel'ı derlerken kullandığı .config dosyasını da /boot altına config-$(uname -r) adıyla kopyalar. Bu demektir ki, örn. kullandığım linux kernel'ının aynısını derlemek istersem, /boot'taki config dosyasını kernel dizinine .config adıyla kopyalayıp make edebilirim. Veya Fedora'nın v5.13.12 kernel'ını derlemek istersem, build sistemi koji'den kernel paketini aratır, x86_64 mimarisi için olan kernel-core paketini indiririm. Sonra rpm2cpio kernel-core-5.13.12-200.fc34.x86_64.rpm | cpio -idmv komutuyla açarım ve içinden çıkan lib/modules/5.13.12-200.fc34.x86_64/config dosyasını .config olarak linux-5.13.12 dizinine kopyalayıp, derlerim. Sonunda ortaya çıkan kernel Fedora'nın aynısı olacaktır (ek okuma: How to install a kernel from koji). Ancak Fedora gibi her makinada çalışması için üretilmiş bir kernel'da gerekli/gereksiz bir çok özelliğin açık olması, (örn. her ne kadar modüler de olsa Fibre Channel), derleme süresini aşırı arttırır. Öyle ki benim bilgisayarımda 5-6 saatte derlendi.

Bu kadar ön bilgiden sonra benim yaşadığım sorun ve çözümüne değinebilirim.


Vmware için Linux Kernel'ını Derlemek

Önce biri VBox'ta biri vmware'de iki makina kurdum. Bunlar ufak farklar dışında aynıydı. Yukarıda anlattığım gibi, standart config üzerine bir kaç özellik ekleyip kernel'ı derledim, /boot dizinine kopyaladım, initramfs'i ve bunları yükleyecek grub konfigürasyonunu oluşturdum. Buraya kadar herşey sorunsuz ilerledi.

Sonra sanal makinaları yeni kernel'la açtığımda VBox'taki çalışırken, vmware'deki çalışmayıp, initramfs'teki rescue shell'e düştü. Yandaki ekran görüntüsünden de görüleceği gibi, /dev altında sd* diskleri yok ve /dev/mapper boş. Bu olağandışı bir durum. Her iki makinada iki disk, ve disklerden birinde CentOS var. İkisini de CentOS'la tekrar açtım, çünkü sorunu tanılamaya yardımcı olacak lsblk, lspci gibi herhangi bir araç initramfs'te yok (Ubuntu Live da bu işi görecektir).

Aşağıdaki çıktıdan görüleceği gibi her iki makinadaki aygıtlara ve bunların kernel modüllerine lspci -k komutuyla baktım.

Vmware'de ata_piix, vmw_vmci, pcieport gibi genel geçer modüllerin yanısıra mptspi diye bir modül var, hem de SCSI denetleyicisi için. Alt taraftaki VBox çıktısındaysa ilginç herhangi bir sürücü yok. SATA controller olarak standart ahci kullanılıyor, mptspi bulunmuyor. Bu modülü biraz araştırdım. mptbase, mptscsih, mptspi sürücülerine ait konfigürasyon "Fusion MPT ScsiHost drivers for SPI" [3] olarak geçiyor, bu da kernelconfig.io'ya göre "Device Drivers/Fusion MPT device support" menüsü altında bulunuyor ve .config'de adı CONFIG_FUSION. Standart .config'de AHCI açık gelirken FUSION kapalı geliyor. Elbette bu seçenek CentOS'ta açık olduğundan onda bir sorun yaşanmıyor.

$ grep AHCI .config
CONFIG_SATA_AHCI=y
# CONFIG_SATA_AHCI_PLATFORM is not set
# CONFIG_SATA_ACARD_AHCI is not set

$ grep FUSION .config
# CONFIG_FUSION is not set

İşte sorunun kaynağı. Tekrar make menuconfig diyip, bu sürücüyü de seçtim. Makina sürekli vmware altında çalışacağından, modül olarak değil kernel'a dahil ederek bir daha derledim. Yeni kernel'i (arch/x86/boot/bzImage) /boot altına kopyalayıp makinayı yeniden başlattığımda makina düzgünce açıldı.




Kaynaklar:
[1]: Why both make clean and make mrproper are used?
[2]: https://en.wikipedia.org/wiki/Loadable_kernel_module
[3]: https://cateee.net/lkddb/web-lkddb/FUSION_SPI.html
 - : https://www.youtube.com/watch?v=WiZ05pnHZqM

Hiç yorum yok:

Yorum Gönder