Aygıtların, sistem üzerinde yürüyen programlarla veya doğrudan işletim sistemleriyle nasıl haberleştiğini daha iyi anlayabilmek adına basit bir C programı ile başlayalım:

...

erisim=open("/dev/ttyS0", O_READONLY); //1

...

read(erisim,&b,1); //2

...

return 0;

 

open() komutu ile aygıt açılır, aygıt düzgün açılırsa 0 dan büyük bir rakam döndürür. read() komutu ise “b” adresine açılan cihazdan 1 bayt bilgi okur.

open() komutundaki “/dev/ttys0” adresini değiştirerek ilgili aygıttan 1 bayt okunabilir, Mesela: “/dev/sdb2” gibi.

Aygıtlar için open() ve read() gibi close(), write(), icotl() gibi çokça fonsiyon bulunur.

Yukarıdaki C kodunu düşündüğümüzde open() komutuna istediğimiz aygıtı girerek o aygıttan 1 bayt bilgi okuyabiliyorduk, peki bu open() ve read() komutu nasıl komutlar ki tüm cihazlar için çalışabiliyor? Mesela, bir sabit disk için de bir klavye için de open() ve read() fonksiyonları çalışıyor ve hatasız sonuç getiriyor? -Aslında open() ve read() birer temsili komut gibi; gelin detaylı inceleyelim:

Bu sisteme “Sanal Dosya Sistemi (Virtual File System)” deniliyor ve bu sistem sayesinde aslında open() ve read() komutunu kullandığımızda aygıta ait başka komutlar çalıştırılıyor.

Linux çekirdeği içerisinde, karakter aygıtları (fare, klavye, seri kanal vb) ve blok aygıtları (cdrom, sabit diskler vb.) için birer tablo tutulur. Bu tabloların satır başlıkları aygıta ait major numarasını, sütun başlıkları ise open() ve read() gibi temsili komutları tutar, satır ve sütun kesimlerinde ise temsili komut çağrıldığında hangi komut çalıştırılacaksa o komut ismini tutar.

Görselde de ifade edildiği gibi, 4 numaralı major numarasın sahip aygıt (/dev/tty) için open() komutu kullanıldığında aslında aygitiAc() komutu calistiriliyor.

Aygıtlara ait major numaralarını öğrenmek için;

Kırmızı: Aygıt biçimi (blok, karakter) Sarı: Major numarası Mavi: Minor numarası

Farklı cihazları birbirinden ayırt etmek için “Major Numarası”; aynı tip cihazları birbirinden ayırt etmek için ise “Minor Numarası” kullanılır: SCSI disk ile seri kanalı biribirinden ayırt etmek için 2 farklı major numarası; birden fazla seri kanal varsa bunları biribirinden ayırt etmek için minor numarası kullanılır.

Görüldüğü üzere, open(), close(), read(), write(), ioctl() gibi cihaza ait bütün giriş/çıkış fonksiyonları, ilgili tablolar yardımı ile aygıta ait yazılımı kullanarak üretici tarafından yazılmış özel fonksiyonları çağırıyor. Cihaza ait sürücü yüklü değilse, fonksiyon çağırıldığında hata döndürecektir.

Örneğin, major numarası 4, minor numarası 64 olan bir aygıta ait open() fonksiyonu çağırmak istediğimizde;

  1. Tablonun open() içeren sütununa gidilir ve sütun seçilir,
  2. Sütuna ait 4. satıra (major numarası, major numaralarına göre aygıtlar satır satır sıralanır) inilir,
  3. Kesişen hücrede “call sopen(64)” işletilir. Fonksiyon parametre olarak aygıtın minor numarasını almıştır.

Yukarıda temsili olarak verilen sopen() fonksiyonunun adı, sürücü yazılımını geliştiren kişi tarafından keyfi olarak belirlenebilir ancak; fonksiyonun döndüreceği sonuçlar belirli standartlara sahiptir, bu standartların dışına çıkılamaz.


Kaynakça:

Nazım Koç, Gömülü Linux Sistemleri (İstanbul: Pusula Yayıncılık, 2011)