Linux Kernel Ve Aygıt Ağacı

Unix işletim sistemleri iki parçadan oluşurlar.  Bunları Kernel Uzayı ve Kullanıcı uzayı diye ayırıyoruz. İşletim sisteminin kullanıcıya sunduğu kontrol ve yönetim arayüzleri kullanıcı uzayını(User Space) oluşturur. Arka planda donanımı ve kaynak kullanımını yöneten çekirdek program çalışır. Donanımı kontrol eden ve kullanıcı uzayında çalışan tüm programları yönetip belli kurallara göre çalıştıran bu çekirdek program Kernel Uzayını oluşturur. Özellikle gömülü yazılımcıların linux’ü bu kadar sevmesinin tek bir sebebi vardır, o da;  linux kernel uzayının açık kaynak olması ve müdehale edilebilmesinden kaynaklanıyor.  Gömülü yazılımlıcıların yaşama alanı, donanıma yakın ve düşük seviyede çalıştıkları için kernel uzayıdır.

Monolitik ve mikro kernel olarak iki tip kernel uzayı vardır.  Bu yazıda monolitik kernel’i baz alacağız. Monolitik bir kernelde, tüm işletim sistemi hizmetleri ana thread’den dallanarak çalışır. Bu sayede tüm işletim sistemi aynı hafıza alanını kullanır. Bu yaklaşım zengin ve güçlü donanım erişimi sağlar. Monolitik çekirdeklerin temel dezavantajı, fazla katmandan oluşması sebebiyle sistem bileşenleri arasındaki bağımlılıklardır. Bu yüzden aygıt sürücüsündeki bir hata tüm sistemi çökertebilir.

Monolotik Kernel, temelde çekirdek olarak tüm kernel işlevlerini yerine getiren bir ana bölümden ve bu bölümün çevresindeki aygıt sürücülerinden oluşur.  Bu UNIX sistemlerinin geleneksel tasarımıdır. Monolotik kernel, işletim sisteminin yönetimini sağlamak ve donanımı kontrol etmek ile ilgili her görevi gerçekleştirmek için gereken tüm kodu içeren tek bir programdan oluşur.  Kullanıcı uzayındaki her program, kerneldeki aygıt sürücüleri, zamanlayıcı, sanal hafıza ve hafıza işleme, dosya sistemleri, ağ yığınları gibi hizmetlere erişebilmeleri için birçok sistem çağrısı yapar ve geri dönüş alır.  Tüm işletim sistemi, kernele yapılan bu sistem çağrıları ile çalışır.

Şimdi gelelim esas bizi ilgilendiren kısma, internetten bir göz attığınızda belki yüzlerce kernel çeşidi görürsünüz.  Telefonlar için ayrı bir kernel, sunucular için ayrı bir kernel, kullanıcı bilgisayarları için ayrı bir kernel ve hatta etrafınızdaki her linux cihaz için ayrı bir kernel vardır.  Bu gün büyük şirketler, cihazlarına uygun kernel geliştirmek için milyonlarca dolar para harcıyorlar.  Bu kerneller temelde aynı mimariye ve aynı çekirdeğe sahiptir. Aralarındaki  fark ise, farklı bir şekilde konfigüre edilmiş ve farklı sürücü kodlarının dahil edilmiş olmalarıdır.   Örneğin bir telefonun kullanacağı LCD sürücüsü, bir sunucu için gerekli değildir. Aynı şekilde bir pos cihazının kullandığı kart okuyucu sürücüsü, kişisel bilgisayarlar için gerekli değildir.

Kernel açık kaynak kodlu olduğundan internetten kernel’i indirerek kendiniz konfigure edebilirsiniz.  Google üzerinde “Linux Nasıl Konfigure edilir?” yazdığınızda bununla ilgili bir sürü kaynak bulabilirsiniz.  Kernel’i konfigure etmek için kaynak kodlarının içerisinde konfigurasyon scripti bulunur.  Bu script aracılığı ile mevcut olan sürücüleri seçebilir veya istemediğiniz sürücüleri kapatabilirsiniz. Bu da kernel boyutunuzu düşürür tabi ki.  Kernel’i derlemek için iki şeye ihtiyacınız var. Birincisi, “makefile” ki bu zaten kaynak kodlarının içerisinde bulunur, ikincisi ise bir derleyici. Kernel C dili ile yazıldığı için kerneli derleyeceğiniz uygun bir C derleyicisi seçmeniz gerekiyor. Bu derleyiciyi, derlemek istediğiniz cihazın işlemcisine göre seçiyorsunuz. Örneğin, arm işlemcili bir telefonun kernel’i arm derleyicisi ile derleniyor. İndirdiğiniz kernel’in hangi derleyiciler tarafından desteklendiği bilgisi ayrıyeten kernel içerisindeki README dosyasında da yazılır genellikle.

Konfigurasyon scriptinden sonra, bir kernel üzerinde sürücü geliştirmek ve ya kernel kodlarını, derlemek istediğiniz cihaza göre şekillendirmek için kullanılacak diğer en önemli şey, “Linux Device Tree” dir.  Linux Device Tree nedir ondan bahsedeyim önce.

Linux Device Tree,  .dts uzantılı dosyalara yazılan ve kernel’in kullanılacağı donanımı bir script diliyle tanımlayan açıklamalardır en temelinde.  Bu tanımlamalar sayesinde, kernelin derlenmek istendiği donanım özellikleri kernel kodunun içerisine yazılmak yerine,  .dts uzantılı dosyalarda belirtilir. Kernel derlenirken bu dosyalar baz alınarak, işlemci ve modüllerin gpio pin numaraları , diğer donanım özellikleri koda dahil edilir.   Aygıt ağacı denmesinin sebebi yapısal olarak  her bir düğümün(node) kendi içinde dallanarak ek donanım ve düğümlerin olduğu bir ağaca benzemesinden kaynaklanır.

Örneğin aşağıda kernel’in derlenmek istendiği cihaza ait Uart modülünün device tree yapısı bulunuyor.

Kernel kaynak kodları içerisinde bulunan Dts uzantılı dosyalar bu yapılardan oluşur.  Bu yapılar özellikle Gömülü yazılımcıları ilgilendiriyor. Çünkü kernel’i kendi geliştirdikleri karta göre şekillendirebilmek için bu dosyaları oynamaları gerekiyor.  Bu videoyu izleyerek device tree yapıları hakkında daha ayrıntılı bilgilere ulaşabilirsiniz.

 

 

Kerneldeki sürücüler, linux aygıt ağacı ile bağdaştırıldığı için yanlış tanımlanan aygıt düğümleri(Device node) kernel sürücüsünün düzgün çalışamamasına neden olur.  Örneğin raspberry pi gibi bir geliştirme kartı düşünün ve bu kartta bulunan mikrodenetleyicinin uart modüllerini kullanıcı uzayındaki programlar ile kullanmak için bir sürücü yazılır. Bu uart sürücüsü direk  olarak Linux Aygıt ağacındaki ilgili uart düğümü(Node) ile ilişkilendirilir.

Linux işletim sisteminde herşey bir dosya olarak ifade edilir.  Bu yüzden aygıt sürücüleri de kullanıcı uzayında birer dosyadır aslında. Sürücüsü ve aygıt ağacı düzgün tanımlanmış bir donanım, linux’ün “/dev” klasörü altında düğüm(node) ismiyle görülecektir.  Buradaki dosyalar yani sürücüler sistem çağrıları yapılarak yani bir nevi dosya açma/yazma/okuma işlemi yapılarak kullanılabilir. Bu sayede donanımı yöneten programlar istenilen cihaza göre şekillendirilebilir olur. Yani atıyorum mevcutta yazılmış bir uart sürücüsü tekrar tekrar yazılmaya gerek duyulmadan sadece aygıt ağacı değiştirilerek kullanılabilir.

Yusuf

Yusuf

Bir Mühendis.

Önerilen makaleler

4 Yorum

  1. Avatar

    Oncelikle cok aydinlatici bir yazi olmus gercekten Yusuf bey. Bu guzel zahmetinizden dolayi size cok buyuk minnettarligimi bildirmek isterim. Aslinda 4-5 yildir linux kullanirim ama hic merak etmedim derin detayini. Github da kernel kodunu gorunce ilgimi cekti. Fakat bunlari anlamak boyumu asiyor. Mesela githubda kernel kodunu incelemek isterim nasil calistigini kendi deneyimlerimle anlamak isterim. Bunun icin nereden baslaya bilirim kodu okumak anlamak icin sizce aydinlatici bir `full guide` makale varmidir?
    Tesekkurler bir daha

    1. admin

      Merhaba İlkin bey.

      Yorumunuz için teşekkürler. Kernel kodlarını “https://github.com/torvalds/linux/tree/master/kernel” adresinden indirebilirsiniz. Bu kodlar içerisinden geliştirme yapmak istemeyeceğiniz hatta yapmamanız gereken tek kısım kernelin çekirdek kodlarıdır. Çünkü bu çekirdek kodları kendi içerisinde başlı başına bir algoritmaya ve lisansa tabi. Yani tabi isterseniz yine kurcalayabilirsiniz ama gerek duyulmuyor genellikle. Fakat bu kodlar içerisindeki sürücü ve servis kodlarını dilediğiniz gibi değiştirip kurcalamakta özgürsünüz. Fakat bunu yapmadan önce linux üzerinde küçük modüller yazarak başlayın. Daha sonra kodlar içerisinde ilgili sürücü kod parçasını daha kolay bulup anlayabilirsiniz. Bunun için web sayfamdaki; “https://yusufbulbul.com/2019/07/29/linux-kernel-uzayinda-yazilim-gelistirmek/” bu yazı dizisinden başlayabilirsiniz. Bu arada linüx kodları çok geniştir. Herkes kendi çalıştığı servis ya da sürücü kod parçasını bilir. Fakat tabi temelde tüm sürücü ve servis programları aynı veya benzer kernel sistem çağrılarından faydalanıyor.

  2. Avatar

    Bu gayet anlaşılır ve açıklayıcı yazınız için ben de teşekkür ediyorum.
    Emeğinize sağlık!
    Yazılarınızın devamını diliyorum.

    1. admin

      Yorumunuz için teşekkürler. 🙂

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Translate »