Cuma, Ocak 21, 2005

Uygulamalar Çekirdekle Nasıl İletişim Kurar

Uygulamalar ve çekirdek arasıdaki iletişim sistem çağrıları ile sağlanır. Çekirdek çağrı isteyenin bu çağrıdan yararlanıp yararlanamayacağına karar verir. Örneğin her isteyenin sabit diske veri yazmaması sağlanır.

Linux’ta strace komutu ile, çalıştırılan programların kullandığı sistem çağrılarını görebilirsiniz.

void main()
{
printf("Denemen");
}

Derleyip, strace ile inceleyelim.

siseci:~/kernel# make 1

siseci:~/kernel# strace ./1

execve("./1", ["./1"], [/* 32 vars */]) = 0

...

...

write(1, "Denemen", 7)= 7

....



execve ile yeni bir process başlatılıyor. write ile 1 ile gösterilen dosyaya 7 bayt uzunluğunda "denemen" yazılıyor.

Şimdi yukarıda anlatılanları burada somut olarak görmekteyiz. Uygulamamız çalıştığında write çağrısını kullanıyor. Çekirdek ise burada programın isteğini değerlendiriyor ve eğer uygunsa izin veriyor.

Burada bir noktayı hatırlatmak istiyorum. Biz direk makine koduyla (assambler) çalışıyor dahi olsak. Uygulamamız ve işlemcinin arasında çekirdek bulunduğundan sistem çağrılarını kullanmamız gerekir. Biraz daha açmak gerekirse çekirdeğin yüklenmiş olması işlemcinin artık meşhur protected mode safhasına geçmiş olması demektir. Bu noktadan sonra bizim uygulamamızın çekirdeğin izini olmadan aygıtlara direk erişimi söz konusu değildir.

Konunun daha açıklayıcı olması açısından sistemin başlama anına geri dönelim ve neler olduğuna bir bakalım:

Linux çekirdeği sadece standart bir C programıdır aslında. Yalnızca iki önemli farklılık vardır. C dilinde
yazılan programların başlangıç noktası main(int argc,char **argv) yordamıdır. Linux çekirdeği start_kernel(void) kullanır. Sistem baslarken ve çekirdek yüklenecekken daha program çevresi mevcut değildir. Yani ilk C yordamı çağrılmadan önce bir kaç şey daha yapılmalıdır. Bu isi gerçekleştiren donanım kodu arch/i386/asm/ dizini altında yer alır.


Assembler dili yordamı çekirdeği tam olarak 0x100000 (1 Mbyte) bellek adresine yükler, ardından da başlatma süreci esnasında dışlamalı olarak kullanılan kesme hizmet yordamlarını (interrupt servicing routines), genel dosya tanımlayıcı çizelgeleri (global file descriptor tables) ve kesme tanımlayıcı çizelgeleri (interrupt descriptor tables) yükler. Bu noktada işlemci korunurlu moda girer. Çekirdeği başlatmak için gereksiniminiz olan her şey init& dizini altındadır. Burası çekirdeği doğru düzgün başlatmakla görevlendirilmiş, geçirilen tüm açılış (boot) parametrelerini dikkate alan start_kernel() yordamıdır. İlk süreç sistem çağrıları kullanılmadan oluşturulur (daha henüz sistemin kendisi yüklenmemiştir).


Ayrıca Aşağıdaki tablo'da işlerin genel olarak nasıl yürüdüğünü anlamamıza yardımcı olacaktır. [En kısa zamanda türkçeleştireceğime söz :) ].

Buradaki gösterim basit ve anlaşılabilir olması için yalnızca temel öğeleri içermektedir. Ancak temel yapıyı kavramak için oldukça yeterlidir.




Yukarıda printf fonksiyonun sebep olduğu write çağrısını basitçe gördük. Ancak iş sistem çağrısı gerçekleştiğinde bitmiyor.

Aşağıda read çağrısı ve ardından gerçekleşen olaylar gösterilmiştir.




Şimdi burada neler olduğunu adım adım inceleyelim.

read çağrısın işlevi basitçe herhangi bir veriyi kaynağından alıp, onu isteyen programın bu iş için ayırdığı belleğe kopyalamaktır.

Bir sistem çağrısının çekirdeğe iletilmesi belirli bir "yazılım kesmesi" tarafından gerçekleştirilir. Bu kesme (aynı zaman da "kapı" da denir) x86 işlemcili Linux sistemler için 0x80 kesmesidir.

0x80 kesmesi hakkında not: Programcının işletim sistemi çekirdeğinden sistem servisi alması için kullanılır. Dosya açma, dosya kapama, aygıtlara erişim, terminal'e çıktı gönderme, yeni süreç yaratma gibi işlemleri yaparken çekirdek bize servis sağlar. Bu yapı, her programcının aygıtlar için kendi erişim kodunu tekrar tekrar yazması gibi bir zorluktan kurtarır bizi (ve tabi zaman kazandırır).Birçok programcı 0x80 kesmesini kullanmaz, hatta çoğu hayatında bir yada birkaç kez sadece ismini duymuş olabilir. Bunun nedeni ise bu tür servislerin üst seviye dillerde (HLL) programcının kolay kullanımı için önceden yazılmış fonksiyonlar tarafından yapılıyor olmasıdır. 0x80 kesmesinin direkt olarak kullanılmak zorunda olduğu tek dil Assembly Programlama dilidir.

İstediğiniz sistem çağrısını "EAX" yazmacına (yazmaç=register) atarsınız. Çağrının kabul ettiği parametreleri de geriye kalan yazmaçlara (EBX, ECX gibi) atayarak "0x80" kesmesini çağırırsınız. Şekilde direk olarak görünmese de aslında atanan __NR_read değil buna karşılık gelen çağrı kodudur. Söz konusu çağrı kodu ve __NR_read in alabileceği diğer parametreler /usr/include/asm/unistd.h dosyasında tanımlanmıştır.Ayrıca read ile ilgili man sayfasına "man 2 read" komutuyla ulaşabilirsiniz.

Buraya kadar yapılan işlemler "user space" de (user mode) da gerçekleşti. Basitçe read adlı sistem çağrısını 0x80 kapısını kullanarak "kernel space" e aktardık.
Şimdi bundan sonra kernel space'de (kernel mode da) olanlara bir bakalım.

Çekirdek ilk olarak bütün yazmaçları kaydeder (SAVE_ALL). Bir sonraki adımda EAX yazmacı tarafından yapılan isteğin bellek sınırlarını aşıp aşamdığı kontrol edilir (Check Limit of EAX) [1]. Daha sonra system çağrıları tablosuna bakıp (EAX yazmacındaki isteği kullanarak) uygun fonksiyonu çaliştırır. ( syscall_tab[EAX]() ). Burada çalıştırılacak fonksiyon sys_read fonksiyonudur.

Bir sonraki aşamada dosyaya ilişkin parametreler ve izinler kontrol edilir, eğer herşey uygunsa dosyadaki veri alınır (kopyalanır). Sonuç uygulamanın istediği belleğe kopyalanır ve sonuca dair onay değeri uygulamaya gönderilir.

Bu aşamadan sonra işlem tekrar user mode da devam eder. Uygulama kontrol değerine bakar hatasız ise işlemine devam eder. Artık uygulama istediği verinin hatasız biçimde geldiğini ve hafızadaki yerini bilmektedir.

Bu yazıda sizlere bir uygulamanın çekirdekle olan iletişimini elimden geldiğince sade ve basit bir biçimde anlatmaya çalıştım.
Umarım faydalı olmuştur.


Serbülent ÜNSAL
serbulentunsal (et) meds.ktu.edu.tr

Not: Bu belgedeki bilgiler GNU/Linux sistemler için olmasına karşın genel olarak diğer pek çok sistem içinde doğrudur.

[1]:İşlemcilerdeki hafıza oruma mekanizması ile ilgili daha ayrıntılı bilgi için (http://www.cs.ucsb.edu/~cs170/notes/memory/)

Kaynaklar:

http://www.acikkod.org/yayingoster.php?id=30
http://www.linuxfocus.org/Turkce/January1998/article19.html
http://www.core.gen.tr/Security/Documents/12.html
http://www.freebsd.org/doc/en_US.ISO8859-1/books/design-44bsd/overview-kernel-service.html
http://plg.uwaterloo.ca/~itbowman/CS746G/a1/
http://www.linux-mag.com/2000-11/gear_01.html

Salı, Ocak 18, 2005

User mode ve Kernel mode nedir ?

Daha önce kulağıma çalınan ancak ne olduğunu tam olarak bilmediğim bu iki terim hakkında ne yazik ki tam ve açıklayıcı bir Türkçe kaynağa rastlayamadım. Bu yüzden öğrendiklerimi özetleyen kısa bir bilgi notu yazmaya karar verdim. Bu notun bir kopyasını tr.wikipedia.org adresinde User mode ve Kernel mode başlıkları altında bulabilirsiniz.


Önce birkaç terime açıklık getirelim.

Protected mode: x86 (286 ve üstü intel ailesi ve uyumlu (amd,via vb.) ) işlemcilerde bellek adreslerine erişim belirli kısıtlamar çerçevesinde olur. Yani her uygulama her istediği bellek adresini istediği gibi kullanamaz. Her bellek bölgesinin erişim hakları descriptor denen kayıtlarla saklanır. Bu kayıtların arka arkaya dizilimi ile hafızanın tamamen adreslendiği bellek haritası ( memory map ) oluşturulur.

CPL: Code Privilege Level (Kod Yetki Düzeyi). x86 işlemcilerde descriptor tarafından ayarlanan ve o kodun çalıştığı yetki seviyesini (privilage level) gösteren 2 bitlik değer. 0 en yüksek yetki seviyesidir, ring 0 diye geçer. 3 ise en düşük değerdir, ring 3 olarak geçer. Arada ring 1 ve ring 2 diye tanımlanan başka seviyeler olmasına karşın işletim sistemlerinin çoğu yalnızca ring 0 ve ring 3 seviyelerini kullanırlar.

Kernel Mode

Linux işletim sistemi açılışta kernel mode’da ( ring 0 ) baslar. Sistem açılışı sırasında kernel yüklenir yüklenmez işlemci Protected Mode'a geçer ve bunun ardından çalıştırılan tüm programlar User Mode'da çalışır ( bazı donanım sürücüleri hariç ). Kernel mode'da çalışan uygulamalar bütün hafıza adreslerine ve Giriş-Çıkış (harddisk ve benzeri) aygıtlarına tam yetki ile erişirler. Ayrıca bu mode'da iken tüm sistem fonksiyonlarına erişilebilir, hafıza yeniden adreslenebilir.

User Mode

Linux sistemi açılışta kernel mode’da baslar. Sistem açılışı sırasında kernel yüklenir yüklenmez işlemci Protected Mode'a geçer. Bu mode’da uygulamalar sistem için kullanılan fonksiyonları güvenlik açısından direkt olarak kullanamaz. Kullanıcı sadece kendi başlattığı uygulamaların adres alanları içerisinde kalmak suretiyle işlerini yürütebilir. Sistemin güvenli bir şekilde çalışabilmesi için kullanıcıya kısıtlı izinler tanınmıştır. Bu mode'da çalışan uygulamalar sistem kaynaklarına erişmek istediklerinde ring 3 seviyesinde çalışmakta olan çekirdek servisleri aracılığı ile çekirdeğe istek gönderirler. Sistem çekirdeği de eğer uygunsa isteği yerine getirir.


Not 1: Yukarıda yazılanlar Linux işletim sistemi referans alınarak yazılmıştır. Ancak diğer pek çok işletim sisteminde de geçerlidir.

Not 2: Bu belge'yi Tonguç Yumruk'un uyarıları doğrultusunda yeniden gözden geçirdim, kendisine teşekkür ederim. Ayrıca bu gözden geçirme işlemi sırasında bu belgeye rastladım. Konu ile ilgili daha ayrıntılı bilgi isteyenler için oldukça faydalı.



Pazartesi, Ocak 17, 2005

CNN LIVE vs IRAK LIVE

Irak'tan yazan bir kızın günlüğü, internette dolaşırken tesadüfen buldum. Söylenecek fazla birşey yok. Link burda.

Amerikan Özel Birlikleri İran'da

BBC NEWS sitesindeki bu habere göre Amerikan özel birlikleri İran'da bulunuyormuş. Daha Irak'tan çıkamayan Amerika İran'da ne yapacak merakla bekliyorum doğrusu.

Debian Postası

www.Debian-tr.org daki günlüğümüde buraya taşımaya karar verdim. Debian postası ile başlayacak olan bu dizide yaşadığım sorunları ve çözüm yollarını yazarak yeni başlayanlara yol gösterici olmaya çalışacağım.

1- Nerde benim Firefox'um

Yanlis Çözüm: " apt-get install firefox "
Dogru Çözüm: " apt-get install mozilla-firefox "

2-Kurulum dilini Türkçe seçtigim halde þðÝý karakterleri niye yazmiyor ? ve alt_gr tusu niye calismiyor. Bu tuslar hem X serverda hemde terminalde sorunlu.

Çözüm: Herhangi bir metin editörü ile /etc/XF86Config-4 dosyasını açıp "Input Device" kısmında "keyboard" yazan bölümü buluyoruz. Bu bölümde Option "Xkbmodel" "pc105" olarak ve "Xkblaout" "tr" olarak değiştiriyoruz. Kurulumu türkçe ayarlarla yapmama ve klavye olarakta trq seçmeme rağmen nedense "us" idi, öntanımlı değer.

3-firefox'u nasil türkce yapacagim.

Bu sorunun yanıtını debian türkçe listesinde buldum.

Onceki iletide mozilla-firefox-locale-tr paketini bir yabanci
gelistiriciye: Cesar Martinez Izquierdo'ya devrettigim belirtmistim.
Paketin Debian arsivlerine gonderilmesi icin kendisiyle gorusuyorum.
Asagidaki bagda bu calismanin bir urununu bulabilirsiniz. Paketi
hizlica test ettim. Gayet sorunsuz gorunuyor.

http://users.evtek.fi/~k0400388/debian/mozilla-firefox-locale-all/mozilla-firefox-locale-tr-tr_1.0-3_all.deb

Bu paketi kurmak icin once normal bir mozilla-firefox kurulumu yapin:

apt-get install mozilla-firefox

Daha sonra da paketi indirip dpkg ile kurun:

dpkg -i mozilla-firefox-locale-tr-tr_1.0-3_all.deb

--
roktas


4-Gnome'dan Kde ye nasil gececegim.

Soruma 2 yanıt aldım fcn ve Emre'ye teşekkürler. Yanıtlar aşağıda...

"gnome'dan kde'ye nasıl geçeceğim?" sorunuz bende soru işaretleri yarattı. eğer x açılışında nasıl seçim yapacağınızı soruyorsanız, http://ordiluc.net/selectwm adresinde ufak bir program var. incelerseniz işinize yarayabilir. ayrıca benim kullandığım desktop manager programım (gdm) hangi masaüstü yöneticisiyle açılacağını seçme fırsatı veriyor.

kolay gelsin.

Gnome dan kde ye update-alternatives --config x-window-manager komutuyla ya da kdm paketini yukleyip dpkg-reconfigure kdm den kdm yi secip masaüstünü kde olarak seçip login olarak geçebilirsiniz