Kök Dosya Sistemi Oluşturma
Gömülü sistemimizin oluşturulmasında kök dosya sisteminin üretimi önemli adımların başında gelmektedir.
Boot yükleyici ve Linux çekirdeği ile ilgili işlemler tamamlandıktan sonra, çekirdek tarafından / kök dizini altına bağlanacak dosya sistemimizi hazırlamalıyız. Dosya sistemimizin temellerini ise Busybox ile oluşturacağuz.
Busybox projesi 1995 yılında, Özgür Yazılım dünyasının önemli figürlerinden Bruce Perens tarafından geliştirilmeye başlanmıştır. Projenin temel hedefi, 1.44 MB'lık tek bir disket içerisine temel bir Linux kök dosya sistemini ve Linux kurulum uygulamasını sığdırmak idi. O tarihlerde tipik bir Linux kurulum süreci, 2 disket ile başlıyordu. Birinci diskette Linux çekirdeği yer alıyordu. Kök dosya sistemi ise 2. disket üzerinden okunuyordu.
Linux dağıtımının kurulumu süresince bize yardımcı olan kurulum (installer) uygulaması da herhangi bir Linux uygulamasından farklı değildir. Dolayısıyla çalışabilmesi için alt tarafta başta standart C kütüphanesi olmak üzere, çalışan bir Linux dosya sistemine de ihtiyaç duymaktadır. Bunun yanı sıra kurulumun çeşitli aşamalarında fdisk, mount, cp, mkdir, .. vb. temel Linux araçlarının da sistemde yer alması gereklidir.
Busybox projesi derlendiğinde tek bir uygulama dosyası (busybox) oluşmaktadır. Bu tek uygulama içerisinde, pek çok temel Linux uygulamasına ait fonksiyonlar (kabuk, editör, dosya sistemi işlemler, disk bölümleme ve biçimlendirme araçları vb.) yer almaktadır. Busybox uygulaması içerisindeki bu fonksiyonları kullanmak için, ilgili fonksiyon ve fonksiyonun parametreleri busybox uygulamasına verilmelidir. Örnek olarak sistemde mkdir
komutuyla yeni
adında bir dizin yaratmak istersek, bunu busybox
ile şu şekilde yapabiliriz:
Eğer busybox uygulamasını derlerken mkdir
fonksiyonlarını içeren applet
'i de dahil etmiş isek, işlem gerçekleşecektir.
Busybox uygulamamız içerisinde hangi fonksiyonlara destek olduğunu görmek için, uygulamayı parametre vermeden çalıştırıp çıktıyı inceleyebiliriz:
Busybox içerisinde yer alan tüm fonksiyonları, yukarıdaki örnekte gösterdiğimiz şekliyle busybox uygulamasına parametre olarak geçirmek suretiyle kullanmaya kalksaydık, özellikle kabuk betiklerimiz gereksiz tekrarlar nedeniyle oldukça çirkin görünecek, betiklerin okunabilirliği de önemli oranda azalacaktı.
Busybox bu problemi çok basit ama zekice bir yöntemle çözmektedir. Tek bir uygulamadan ibaret olmasına rağmen, make install
komutu verildiğinde, busybox içerisinde desteği eklenmiş tüm fonksiyonlar (uygulamalar) için kendisini gösterecek şekilde sembolik linkler oluşturmaktadır. Örnek olarak, /bin/mkdir
linki /bin/busybox
'ı göstermekte, /bin/cp
linki de aynı şekilde /bin/busybox
'ı işaret etmektedir. Bu şekilde tüm gerekli linkler üretildiğinde artık uygulamaları busybox mkdir
şeklinde değil sadece mkdir
şeklinde çağırmamız mümkün olmaktadır. Sonuçta tüm bu linkler yüzünden aynı uygulama çalışmakta, ancak her defasında farklı isimle çağırmış olduğumuzdan argv[0]
adresinde çağrıldığı programın ismi (örneğin mkdir) yer almaktadır. Busybox içerisindeki komut satırını parse eden bölüm, çağrılma biçimi busybox
dışındaki bir değer ise ve bu değere ilişkin destekler uygulama içerisinde derlenmişse, kendi içinde ilgili fonksiyonu çağırmak suretiyle istenen amacı gerçekleştirmektedir.
Konfigürasyon ve Derleme
Busybox içerisinde pek çok bileşenle geldiğinden, derleme süreci öncesinde hangi bileşenlerden oluşan bir busybox uygulaması üretmek istediğimizi belirlememiz, bunun için bir konfigürasyon dosyası üretmemiz gerekiyor.
Seçenek / kombinasyon sayısı bir kernel derleme süreci kadar devasa olmasa da, hatırı sayılır miktarda seçenek kümesi olduğunu söyleyebiliriz. Tıpkı kernel derleme konfigürasyonu sürecinde olduğu gibi, busybox konfigürasyon ve derleme işlemleri için de Kbuild sistemi kullanılmaktadır.
Menuconfig arayüzü üzerinden konfigürasyon sürecimizin hedefi olan .config
dosyasını üretebiliriz. Bunun için make menuconfig
veya aşağıdaki make hedeflerinden biriyle .config
dosyamızı oluşturabiliriz:
Make Hedefi
Açıklama
menuconfig
İnteraktif menü tabanlı seçi arabirimini çalıştırır
defconfig
Hemen her seçeneğin aktifleştirildiği genel bir konfigürasyon sağlar
allyesconfig
Tüm olası seçeneklerin aktifleştirildiği bir konfigürasyon sağlar
allnoconfig
Tüm seçeneklerin inaktif edildiği, minimum bir konfigürasyon sağlar
android_defconfig
Android platformu için derleme yapılacaksa genel bir seçenek kümesi sağlar
Seçim işlemi tamamlandıktan sonra
komutuyla derleme işlemi yapılabilir. Paralel derleme özelliğini -j
parametresi ile devreye alıp (genelde işlemci çekirdek sayısının 2 katına kadar değer girebilirsiniz) derleme sürecini hızlandırabilirsiniz:
NOT: Bu noktadan sonraki çapraz derleme örneklerinde,
/home/training/toolchains
dizini altınagcc-linaro-arm-linux-gnueabihf-4.9-2014.09_linux
toolchain'inin açıldığı ve PATH ortam değişkeninin uygun şekilde ayarlandığı varsayılmıştır. Cross-Compiler prefix'iarm-linux-gnueabihf-
şeklinde olup EABIHF yani Hard-Float türünde bir toolchain'dir.
Busybox uygulamasını hedef platform için çapraz derlemek istediğimizde, kernel derleme sürecindeki benzer şekilde ARCH
ve CROSS_COMPILE
değişkenlerine atama yapmamız gerekecektir:
Bu şekilde çapraz derleme süreci tamamlanacaktır.
İşlem bitiminde busybox uygulamasını tüm gerekli linkleriyle birlikte bir dizin yapısı içerisinde (aslında kök dosya sistemimizin ilk şablonu da diyebiliriz) make install
komutuyla oluşturabiliriz. Bu komut eğer CONFIG_PREFIX
değişkenine .config
dosyası üretimi sürecinde farklı bir değer atanmadı ise bulunulan dizin altında, _install
şeklinde bir alt dizin açacak ve tüm linkleri ve uygulama dosyasını bu alt dizinlerde oluşturacaktır.
Yukarıdaki örnekte ARM mimarisi için çapraz derleme işlemi sonrası busybox uygulaması ve gerekli linkleri, /opt/cross/rootfs
dizini altında oluşturulacaktır.
NFS Üzerinden Sistemi Açarak İlerleme
Not: Bu noktada NFS Sunucu Kurulumu ve NfsRoot bölümlerini henüz okumadı iseniz incelemeniz önerilir. Kök dosya sistemi ile ilgili burada verilen örnekler BeagleBoneBlack cihazı üzerinde çalıştırılmıştır.
Örneklerimizde öntanımlı beaglebone_defconfig
ile derlenmiş çekirdek, aşağıdaki gibi U-boot komutları ile açılmaktadır:
Yukarıdaki gibi minik dosya sistemimizi /opt/cross/rootfs
dizini altında hazır ettikten sonra, bu dizini NFS sunucumuz üzerinden paylaşıma açıp, cihazımız üzerinden yeni oluşturduğumuz bu dosya sistemiyle açılış yapmayı deneyelim.
Açılış sürecimizin yukarıda belirtilen şekliyle sonlandığını gördük.
Daha önceki aşamalarda, Linux çekirdeğinin açılıştaki tüm işlemleri başarılı olarak tamamlaması halinde son 2 işlem olarak, kök dosya sistemini mount edip, kök dosya sistemi üzerinden bir adet uygulamayı başlatacağını ifade etmiştik. Yukarıdaki çıktıya baktığımızda kök dosya sisteminin NFS üzerinden başarılı bir şekilde mount edildiğini görmekteyiz:
Fakat daha sonra init
uygulamasının çalıştırılamadığını ve kernel panic durumu oluştuğunu görmekteyiz:
Neden böyle bir problem oluştu?
Problemin nedeni üretmiş olduğumuz dosya sistemimizde /bin/busybox
'ı gösteren bir çok link olmasına rağmen, toplamda sadece 1 adet binary uygulama bulunmakta, paylaşımlı kütüphane dosyası ise hiç bulunmamaktadır. Hatta paylaşımlı kütüphaneleri tutacağımız lib
dizini dahi henüz sistemimizde mevcut değildir. Yapmamız gereken, hedef platform için çapraz derleme yaptığımız busybox
uygulamamızın bağımlı olduğu kütüphaneleri bularak, kök dosya sistemimizdeki lib
dizini altına kopyalamaktır.
Öncelikle derlemiş olduğumuz busybox
binary dosyasının kütüphane bağımlılıklarını bulalım. Bunun için readelf
uygulamasını -d
parametresi ile çağırabiliriz:
Görüldüğü üzere libc.so.6
ve libm.so.6
kütüphanelerine ihtiyaç duymaktadır. Öncelikle kök dosya sistemimizde henüz mevcut olmayan lib
dizinini oluşturalım:
Sonrasında ihtiyaç duyulan 2 kütüphaneyi kopyalayalım. Peki bu kütüphaneleri nereden kopyalayacağız? Kendi geliştirme bilgisayarımızın /lib
dizini altındakileri kopyalayamayız.
Oluşturacağımız kök dosya sistemine zaman zaman bu şekilde gereken kütüphaneleri kopyalamamız gerekecektir. Bu işlemleri çoğunlukla öncelikle ilgili kütüphaneyi ayrı bir yerde hedef platform için derleyerek, sonrasında kütüphane dosyalarını kök dosya sistemimiz altına kopyalayarak gerçekleştireceğiz.
Ancak libc.so.6
, libm.so.6
gibi temel kütüphaneler zaten kullandığımız toolchain içerisinde yer almaktadır. Bu kütüphaneleri yeniden derlemek, bir tür toolchain üretim süreci de gerektirdiğinden, çapraz derlemeyle ilgili bölümde de anlattığımız üzere yeniden üretmek yerine toolchain içerisinden çıkan versiyonlarını kullanmak daha sağlıklıdır.
Kullandığımız ARM eabihf toolchain'i için bu dosyalar, toolchain ana dizinini referans aldığımızda, ./arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf
dizini altında yer alır. Bulmakta sorun yaşarsanız toolchain ana dizininde iken:
gibi bir komutla da arama yapıp bulabilirsiniz.
Şimdi her iki kütüphaneyi kök dosya sistemimize kopyalayalım:
Sistemimizi tekrar NFS üzerinden açtığımızda problemin devam ettiğini göreceğiz. Busybox uygulamamızın ihtiyaç duyduğu kütüphaneleri kök dosya sistemimize attık ancak paylaşımlı kütüphane bağımlılığı olan herhangi bir uygulamayı çalıştırabilmek için aynı zamanda ld.so
kütüphanesine de ihtiyaç bulunmaktadır. Bu kütüphane toolchain versiyonlarına göre ld-linux.so.2
, ld-linux.so.3
, ld-linux-armhf.so.3
gibi isimlerde bulunabilir. Bizim kullandığımız ARM eabihf toolchaini içerisinde bu dosya, ld-linux-armhf.so.3
şeklindedir ve bunun da kök dosya sistemine kopyalanması gereklidir:
ARM eabihf toolchain ile çalışan sistemimiz için son bir işlem daha yapmamız gerekiyor. ld-linux-armhf.so.3
loader uygulaması, aynı anda eabihf ve eabi sistemleri destekleyebilmek için, yükleyeceği diğer kütüphaneleri /lib/arm-linux-gnueabihf
dizini altında arar. Aynı anda her iki ARM ABI ile çalışmak pek karşılaşılan bir durum değildir. Bu nedenle genellikle /lib/arm-linux-gnueabihf
dizini /lib
dizinini gösteren bir sembolik link olarak oluşturulur:
Artık tüm bileşenlerimiz hazır görünüyor. Cihazımızı tekrar NFS üzerinden açmayı denediğimizde, bu defa açılış sürecinin gerçekleştiğini görmekteyiz.
/etc/inittab
İyileştirmeleri
/etc/inittab
İyileştirmeleriArtık açılan bir sistemimiz var. Fakat göreceğiniz üzere seri konsol ekranımızda aşağıdaki mesajlar sürekli olarak çıkmakta:
Sistemimiz açılmış ve çalışıyor durumda olmasına rağmen bu hata mesajları yüzünden konsolu efektif kullanamıyoruz. Buradaki problem sistemimizde henüz bir /etc/inittab
dosyası olmadığı için busybox init uygulamasının öntanımlı bir inittab
dosya içeriği varmış gibi çalışmasından kaynaklanıyor. /dev/ttyXX
aygıtları sistemimizde yer almadığından uygulamayı çalıştıramamakta ve tekrar tekrar yaptığı denemelerden kaynaklanan hata mesajları görüntülenmektedir.
Örnek bir inittab
dosyasını busybox kaynak kodlarını açtığımız dizinde, examples/inittab
yolunda bulabiliriz. Bu dosyanın içeriği Init Süreci'nin anlatıldığı bölümde detaylandırılmıştır.
Sistemimiz için aşağıdaki inittab
dosyasını kullanacağız:
Yukarıdaki içeriğe sahip dosyayı /opt/cross/rootfs/etc/inittab
şeklinde oluşturup ardından sitemimizi tekrar açmayı denediğimizde, daha önce aldığımız hata mesajlarının ortadan kalktığını ama yenilerinin geldiğini görmekteyiz:
/etc/acilis
dosyamızı henüz hazırlamadığımız için onunla ilgili aldığımız hata normaldir. Ancak sonrasında sürekli /dev/null
dosyasının yer almadığına dair hatalar almaktayız ve bu hata mesajları yüzünden gene konsolumuzu kullanamıyoruz. Kullandığımız çekirdek içerisinde DEVTMPFS ve DEVTMPFS_MOUNT desteği açıktır dolayısıyla /dev
dizini altındaki aygıt dosyalarının çekirdek tarafından otomatik üretilmesi gerekirdi (detaylar için Devtmps Dosya Sistemi bölümüne bakınız). Buna rağmen /dev
dizini altına bu özel dosya sisteminin çekirdek tarafından otomatik olarak bağlanamadığını görüyoruz. Bunun çok basit bir nedeni var: minik dosya sistemimizde henüz /dev
dizini mevcut değil.
Mount işleminin başarılı olabilmesi için gerekli şartlardan biri, mount edilecek dizinin de öncesinde sistemde bulunmasıdır (örneğimizde /dev
dizini).
Bu sorunu çözmek için kök dosya sistemimizde aşağıdaki komutla /dev
dizinini oluşturalım:
Sonrasında sistemi tekrar NFS üzerinden açalım:
Nihayet sistemimizi görece uygun bir şekilde açmayı başardık. Mesajları incelediğimizde devtmpfs
mount işleminin gerçekleştiğini görüyoruz. /etc/acilis
betiğimiz henüz hazır olmadığından hata alıyoruz ancak konsola düşmeyi başardık. ls /dev
komutuyla /dev
dizini altındaki dosyaları görebiliriz.
Şimdi çalışan uygulamaların listesini ps
komutuyla almayı deneyelim:
Görüldüğü üzere /proc
dizininin sistemde olmadığına dair bir hata alıyoruz ve process listesini de göremiyoruz.
Sistemimizi yeniden başlatmayı deneyelim:
Bu işlem için de /proc
dizinine ihtiyaç olduğu görülüyor. Çalışan bir Linux sisteminde proc
dosya sisteminin /proc
altına mount edilmiş durumda olması önemlidir. Bu dizin altındaki pek çok dosya ve dizin üzerinden, kullanıcı kipindeki uygulamalar çekirdek ile haberleşebilir ve bir takım işlemleri gerçekleştirebilirler.
Şu ana kadar proc
dosya sistemini mount etmiş olmamamıza rağmen sistemimiz -yeterince işlevsel olmasa da- çalışıyordu, dolayısıyla bu tarz işlemler için çekirdek tarafından bir yardım beklememeliyiz. Bu süreci kullanıcı kipinde gerçekleştirmemiz lazım. Sistem her açıldığında mount
komutu ile proc
dosya sistemini /proc
dizini altına bağlamalıyız.
/dev
dizini için yaptığımız örnekte olduğu gibi, öncesinde /proc
dizinini kök dosya sistemimizde oluşturalım:
Şimdi /etc/acilis
betiğini /opt/cross/rootfs/etc/acilis
ismiyle oluşturmaya başlayalım:
Dosyayı oluşturduktan sonra çalıştırma haklarını vermemiz gerekiyor:
Tekrar sistemi NFS üzerinden açtığımızda hiç hata almadan sistemin açıldığını görebiliriz:
Artık ps
, top
, ifconfig
, reboot
vb. pek çok uygulama olması gerektiği gibi çalışmaya başlayacaktır. reboot
komutunu tekrar deneyelim:
Reboot gerçekleşti ancak /etc/kapanis
uygulaması henüz hazır olmadığından bir hata mesajı aldık. Bu dosyayı da oluşturalım. Temel olarak kapanış sürecinde, tüm mount edilmiş dosya sistemlerinin unmount edilmesini sağlamamız yerinde olacaktır. Unmount işlemi Linux Page Cache tablolarının depolama ortamlarına yazılmasını tetikler, böylece kapanış sırasında veri kaybı sorunu yaşamazsınız. Aksi takdirde Write-Back mekanizması nedeniyle veri kayıplarıyla karşılaşabilirsiniz.
Aynı şekilde çalıştırma haklarını vermemiz gerekiyor:
Last updated
Was this helpful?