32 Bit Intel İşlemcilerde Koruma Mekanizması


Çok işlemli (multiprocessing) sistemlerde kullanılan modern ve güçlü mikroişlemcilerin çoğu bir koruma mekanizmasına (protection mechanisms) sahiptir. Intel 80286 ile birlikte segment tabanlı, 80386 ile birlikte de sayfa tabanlı koruma mekanizmasına sahip olmuştur. ARM işlemcilerinin pek çok modelinde, PowerPC, Itanium, SPARC gibi RISC tabanlı modern işlemcilerde de koruma mekanizması vardır.

Koruma mekanizmasının üç yönü vardır


  • Bellek Koruması (Memory Protection): Çok işlemli sistemlerde tüm prosesler aynı fiziksel bellek üzerinde çalışırlar. İşte böyle bir çalışma sırasında bir prosesin (yani çalışan programın) kendi alanı dışına çıkarak başka proseslerin kullandığı bellek bölgelerine erişememesi gerekir. Aksi takdirde bir proses başka bir prosesin bellek alanını bozabilir, değiştirebilir ya da oradaki verileri çalabilir. 



  • Komut Koruması (Instruction Protection): Her prosesin her makine komutunu kullanması sistem güvenliğini tehlikeye atabilmektedir. Çünkü bazı makine komutları eğer rastgele bir biçimde ya da özensiz olarak kullanılırsa sistemin çökmesine yol açabilir. Örneğin Intel işlemcilerindeki CLI (Clear Interrupt Flag) makine komutu işlemcinin kesme bayrağını reset'lemektedir. Bu durumda işlemci donanım kesmelerine yanıt vermez. Bu ise tüm sistemin hemen çökmesine yol açabilecek bir durum oluşturur. CLI komutunun dışında tehlikeli olabilecek başka makine komutları vardır. Bu komutların yetkisiz ve sıradan prosesler tarafından kullanılmaması gerekir. 


  • IO Koruması (IO Protection): Merkezi işlemci (CPU) pek çok yerel işlemciye bağlıdır ve onlara elektriksel olarak komutlar gönderebilmektedir. Yetkisiz ve sıradan proseslerin önemli IO portlarına komutlar göndermesi de sistemi çökertebilir. Bu nedenle sistem güvenliği açısından sıradan bir prosesin önemli olabilecek IO portlarına erişiminin engellenmesi gerekir.


Şüphesiz koruma mekanizması bazı proseslere uygulanıp bazılarına uygulanmayacak biçimde esnek olmalıdır. Örneğin işletim sisteminin kodları koruma mekanizmasının denetiminden muaf olmak zorundadır. Çünkü işletim sistemi bir kaynak yöneticisidir ve kaynakları yönetirken de her türlü işlemi yapabilecek durumda olmalıdır. Benzer biçimde aygıt sürücüleri ve çekirdek modülleri de yaptıkları işin gereği olarak koruma mekanizmasından muaf olmak durumundadır.

Intel işlemcileri koruma mekanizması için 4 dereceli bir yetkilendirme modeline sahiptir. Ancak 4 dereceli yetkilendirmenin pratikte pek kullanışlığı olduğu söylenemez.



Bu nedenle Intel işlemcilerini kullanan Windows - Linux gibi sistemler 4 yetki derecesi yerine yalnızca iki yetki derecesini kullanmaktadır. Benzer biçimde Intel dışındaki diğer işlemci aileleri de 2 dereceli bir yetki sistemine sahiptir. Bu yetki derecelerinin birine "çekirdek modu (kernel mode)" diğerine ise "kullanıcı modu (user mode)" denilmektedir. Pek çok ayrıntı söz konusu olsa da kabaca çekirdek modunda çalışan kodların hiçbir koruma engeline takılmadığını söyleyebiliriz. Ancak kullanıcı modunda çalışan kodlar için işlemciler katı bir koruma denetimi uygulamaktadır. İşletim sistemlerinin kodları, aygıt sürücüler, çekirdek modülleri "çekirdek modunda" çalışan kodlardır. Bunların dışındaki tüm programlar (örneğin Chrome, Word gibi programlar ya da bizim yazdığımız programlar) kullanıcı modunda çalışırlar.

Daha önceden de belirtildiği gibi Intel işlemcileri reset edildiğinde "gerçek mod (real mode)" denilen bir moddan çalışmaya başlar. Gerçek mod işlemcinin 1978 yılında tasarlanmış olan 8086 işlemcisi gibi çalıştığı moddur. (DOS işletim sisteminin ilk kez 8086 işlemcisi için yazılmıştır.) Gerçek modda koruma mekanizması kullanılamamaktadır. Koruma mekanizmasının kullanılabilmesi için işlemcinin korumalı moda (protected mode) geçirilmesi gerekir. Intel işlemcilerinin korumalı moda geçirilmesi CR0 isimli bir kontrol yazmacının en düşük anlamlı bitinin 1 yapılmasıyla sağlanır. Bu yazmaç tamamen koruma mekanizmasıyla ilgili işlemlere yönelik bitlere sahiptir. CR0 yazmacının bitleri şöyledir:



Intel’de CR0 ve diğer kontrol yazmaçları diğer yazmaçlar gibi aritmetiksel ve bitsel işlemlere sokulamazlar. Bu yazmaçlar ancak başka genel amaçlı yazmaçlar ile MOV işlemine sokulabilmektedir. O halde işlemciyi korumalı moda geçirme işlemini aşağıdaki gibi bir kodla yapabiliriz:

mov eax, cr0
or     eax, 1
mov cr0, eax

Intel işlemcileri korumalı moda geçirildiğinde çalışma biçimlerinde önemli farklılıklar oluşmaktadır. Bu nedenle bunları korumalı moda geçirmeden önce bizim bazı hazırlıkları yapmış olmamız gerekir. Ayrıca Intel işlemcilerinde koruma mekanizmasını yalnızca koruma amacıyla kullanılan bir mekanizma olarak düşünmek de doğru değildir. Tasarım gereği (geçmişe doğru uyumun korunması ile de ilgili olarak) bu işlemcilerin bazı özellikleri ancak koruma mekanizması aktive edildiğinde kullanılabilmektedir.

32 Bit Intel Ailesinde çağırma biçimi (calling convention) kavramı

Fonksiyonların çağrılması ve geri dönüş değerlerinin alınması konusundaki belirlemelere çağırma biçimi (calling convention) denilmektedir. Derleyicilerin bir fonksiyonu derlerken stack'e parametreleri hangi sirayla push edeceginin veya parametrelerin kullanılacak register'a hangi sıraya göre atılacağı gibi kuralların belirlendiği modeldir. Dolayisiyla farkli diller arasinda veya farklı ortamlar arasinda kullanilacak olan fonksiyonlarin bildiriminde bunu belirtmek gerekir.


Her programlama dilinde veya sistemde farklılık gösterebilir. Her dillin kendine ait çağırma biçimi olabilir hatta assembly ile istedigimiz biçimde convention oluşturabilir ve kullanabiliriz. Fakat bunların taşınabilir ve farkllı dillerle kullanılabilir olması durumunda standartlara uyma yükümlülüğü vardır. Özetle şu sorulara cevap bulmaya çalışır:

  • Çağrılan fonksiyon hangi yazmaçları bozma hakkına sahiptir, hangi yazmaçları korumak zorundadır?
  • Çağıran fonksiyon ile çağrılan fonksiyon arasında parametre aktarımı nasıl yapılacaktır?
  • Çağrılan fonksiyonun geri dönüş değeri çağrılan fonksiyona nasıl aktarılacaktır?
  • Parametre aktarımı için Stack kullanıldı ise stack'i düzenleme işi kime aittir?


Çağırma biçimi konusu C standartlarını ilgilendiren bir konu değildir. Çünkü C standartları böylesi aşağı seviyeli belirlemeleri derleyicilere bırakmıştır. Dolayısıyla çağırma biçimlerini oluşturmak için gereken anahtar sözcükler derleyicilerde bir eklenti (extension) biçiminde bulunurlar. Çağırma biçimlerine ilişkin anahtar sözcükler genel olarak tür belirten sözcük ile fonksiyon isimlerinin arasına yerleştirilmektedir. Örneğin:

  • Microsoft derleyicilerinde çağırma biçimleri yukarıdaki örnekte olduğu gibi iki alt tire ( __ ) ile başlayan anahtar sözcüklerle temsil edilmektedir. 

void __cdecl foo(int a, int b) {
   
}


  • gcc derleyicilerinde ise fonksiyon özellikleri (function attributes) biçimindeki bir sentaks ile temsil edilir. 

void __attribute__((cdecl)) foo(int a, int b) {
   
}

Harvard & Von Neumann Mimarileri

3:20 AM
Harvard mimarisi, veri ve komutların Merkezi İşlem Birimine ( MİB veya CPU ) giden kanallarının ayrılması ile oluşturulmuş bilgisayar tasarımıdır. Von Neumann mimarisi, veri ve komutları tek bir yığın (depolama) biriminde bulunduran bilgisayar tasarımıdır.



Von Neumann mimarisi

Verilerin ve program kodlarının aynı hafıza birimi üzerinde bulunduran tasarımdır. Von Neumann mimarisinin temel tasarımı aşağıdaki gibidir:


"von Neumann mimarisi" isim olarak John von Neumann'ın 1945 tarihli makalesine dayanır. Bellek ile Merkezi işlem biriminin (MİB) ayrılması von Neumann dar geçidi olarak bilinen soruna yol açmıştır. Bu sorun MİB ile bellek arası veri taşıma hızının, bellek miktarına göre çok düşük olmasından kaynaklanmaktadır. Bu nedenle, CPU zamanın büyük çoğunluğunu bellekten istenilen verinin gelmesini beklemekle geçirir. Son yıllarda CPU'ların hızları ile bellek erişim hızlarının arasındaki farkın açılması ile bu sorun daha da büyümüştür. Sorunu hafifletmek adına cache memory ve branch prediction geliştirilmiştir. von Neumann mimarisinin dar geçit sorunu dışında, en olumsuz yanı ise hatalı yazılımların (buffer overflow gibi) kendilerine, işletim sistemine ve hatta diğer yazılımlara zarar verebilme olasılığıdır.




Harvard mimarisi

Harvard mimarisi, ismini ilk kez bu mimariyi kullanan bilgisayar Harvard Mark I'den almıştır. Bu mimariyi kullanan makinalar, veriler ile komutlar arasında herhangi bir köprü bulundurmazlar. Veri adresi ile program (komut) adresinin adresleme boyutları farklıdır. Harvard mimarisinin temel tasarımı aşağıdaki gibidir:


Günümüz bilgisayarlarında tam anlamıyla kullanıldığı söylenilemez. Yine de Von Neumann mimarisi ve Harvard mimarisinden ortak özellikler günümüz teknolojisinde kullanılmaktadır.


Von Neumann vs Harvard


  • Von Neumann mimarisinde, işlemcinin doğası gereği ya komutlarla ya da verilerle uğraşmaktadır. Çünkü ikisi de aynı belleği paylaşmaktadır. İkisinin aynı anda olması durumu söz konusu değildir. 
  • Harvard mimarisini kullanan bir bilgisayarda ise komut ve veriler ayrı tutulduğu için, işlemci aynı esnada hem komutları değerlendirip hem verileri işleyebilir. Bir önbelleğe de gerek yoktur. Bu Harvard mimarisine bir avantaj sağlasa da; Von Neumann mimarisinde komutlar verilerle bir tutulduğundan, program kendi kendine değişim gösterebilir. 
  • Harvard mimarisinde komutlar ile veriler arasında bir kanal yoktur bu yüzden kodların içine veri gömülmüş programlar çalıştırılırken veya kendi kendine değişim gösterilecek programlar için Von Neumann mimarisi temel alınır.
  • Bellek adresleri açısından Harvard mimarisi iki ayrı adres kullandığından; boş komut adresi boş veri adresinden de farklı olacaktır. Von Neumann mimarisinde ise ikiside aynı adresi paylaşır.

Değiştirilmiş Harvard mimarisi

Değiştirilmiş Harvard mimarisi, Harvard mimarisindeki veri/komut bağlantısının eksikliğini gidermesi amacıyla yapılan tasarımsal düzenlemelere verilen isimdir. İşlemci halen veri ve komut erişimine de sahip olsa da aralarında bağlantılar mevcuttur. Bu düzenlemelerden en önemlisi aynı bellek adresi tarafından desteklenen iki ayrı önbellek kullanmasıdır. Biri komutları, biri verileri tutar. Önbellekte işlem yapılırken Harvard mimarisinin, asıl bellekte işlem yapılırken Von Neumann mimarisinin uygulandığını söyleyebiliriz. Günümüzde kullanılan yeni bilgisayar teknolojilerinde buna benzer mimariler sıkça kullanılmaktadır fakat isimlendirilmesinde ne Von Neumann ne de Harvard demek doğru değildir. Ayrıca komutları, okunabilir verilermiş gibi göstermek de değiştirilmiş Harvard mimarisine örnek gösterilebilir. 


PE ve ELF Çalıştırılabilen Dosyalarındaki Bölüm (Section) Kavramı

3:18 AM ,

PE (Portable Executable) | ELF (Executable and Linkable Format) 



Bugün için en çok kullanılan çalıştırılabilir (executable) dosya formatları PE ve ELF’tir. PE formatını Microsoft 32 bit Windows sistemleri ilk çıktığında tasarlamıştır.  Microsoft daha önce 16 bit Windows 3.X sistemlerinde NE (New Executable) denilen bir format kullanmıştır. Microsoft’un DOS’ta kullandığı çalıştırılabilen dosya formatı da MZ (by Mark Zbikowski = aynı zamanda exe'yi tasarlayan kişi) formatıydı. 


UNIX/Linux dünyasında da pek çok çalıştırılabilir dosya formatı denenmiştir. "a.out" isimli format uzun süre pek çok UNIX türevi sistemde kullanılmıştır. Linux'te başlangıçta bu formatı kullanıyordu. Artık UNIX türevi sistemlerin büyük kısmı ELF formatını birincil çalıştırılabilen format olarak desteklemektedir. Ayrıca bir işletim sistemi birden fazla çalıştırılabilen dosya formatını destekliyor olabilir. Örneğin Linux sistemleri ELF formatının yanı sıra hala klasik "a.out" formatını da desteklemektedir. Windows’un pek çok versiyonu NE ve MZ formatlarını da desteklemiştir. PE ve ELF formatlarının 32 bitlik ve 64 bitlik birbirine çok benzeyen biçimleri de vardır. Böylece bazen bu formatlar PE32, PE64, ELF32, ELF64 isimleriyle de belirtilmektedir. PE ve ELF formatları genel tasarım olarak aslında birbirlerine benzemektedir. Her iki formatta da önemli bilgilerin dosyanın neresinde bulunduğunu gösteren bir başlık (header) kısmı vardır. Her iki format da bölümlerden (sections) oluşmaktadır. Bu formatlara sahip bir program çalıştırılmak istendiğinde işletim sistemi çalıştırılabilen dosyayı açar formattaki bölümleri inceler ve bölümleri belleğe (RAM’e) yükler.



İşletim sisteminin çalıştırılabilen dosyayı okuyarak çalıştırmak üzere belleğe yükleyen kısmına kavramsal olarak yükleyici (loader) denilmektedir. Bölümler aynı özelliklere sahip ardışıl sayfalardan (page) oluşmaktadır. Bölümlerin birer isimleri vardır. ELF ve PE formatında geleneksel olarak bölümler başında "." olacak biçimde isimlendirilmektedir. Tabii aslında böyle bir zorunluluk yoktur. İşletim sistemi bölümler için bellekte yer ayırıp içini çalıştırılabilen dosyadan ilgili alanları okuyarak yüklemektedir.

PE ve ELF Formatlarındaki Çok Karşılaşılan Bölümler



PE ve ELF formatlarında en çok karşılaşılan bölümler şunlardır:

.text Bölümü: 

Bir programın bütün makine kodları (yani kaynak kodları) bu bölümde bulunur. Yani yukarıdaki C programında programdaki main, foo, bar ve tar fonksiyonlarının kodları .text bölümüne yerleştirilmektedir.

.data Bölümü:

Bu bölümde ilk değer verilmiş global değişkenler ve static yerel değişkenler tutulmaktadır. Yani örneğin yukarıdaki C programında g_a ve count değişkenleri derleyici tarafından tipik olarak ".data" bölümünde tutulacaktır. Derleyiciler ilk değer verilmiş global değişkenleri ilk değerleriyle birlikte çalıştırılabilen dosyanın ".data" bölümüne yerleştirirler. İşletim sisteminin yükleyicisi de onları bu bölümden alıp blok olarak fiziksel belleğe yüklemektedir. Bu nedenle ".data" bölümündeki değişkenlerin çalıştırılabilen dosyada yer kaplamaktadır. Ancak bazı çalıştırılabilen dosya formatları bölümler içerisinde hangi ilk değerden ne miktarda olduğunu tutma yeteneğine sahiptir (örneğin Windows’un PE formatı böyledir). Böylece aşağıdaki gibi global bir dizi bu sistemlerdeki çalıştırılabilen dosyalarda çok fazla yer kaplamayabilir:

int g_x[1000000] = {1, 2, 3};

Ancak ELF gibi bazı formatların bu yeteneği yoktur. Dolayısıyla bu formatlarda yukarıdaki dizinin hepsi ".data" bölümünde ilk değerleriyle bulunacak, dolayısıyla bu da çalıştırılabilen dosyanın uzunluğunu büyütecektir.

.rdata | .rodata Bölümleri: 

PE formatındaki ".rdata", ELF formatındaki ".rodata" bölümleri global ve static read-only verileri tutmak için düşünülmüştür. String ifadeleri genellikle bu sistemlerdeki derleyiciler tarafından bu bölümlerde saklanmaktadır. Örneğin yukarıdaki C programında g_b, g_name ve ival değişkenleri derleyici tarafından tipik olarak ".r(o)data" bölümünde tutulacaktır. Windows ve Linux’un yükleyicileri bu bölümlerdeki bilgileri "read-only" sayfalara yüklerler. Dolayısıyla programın çalışma zamanı sırasında buradaki değerler değiştirilmek istenirse exception (page fault) oluşur.

.bss Bölümü: 

Bu bölümde ilk değer verilmemiş global değişkenler (g_c, g_d) ve ilk değer verilmemiş static değişkenler tutulmaktadır. Bunlara ilk değer verilmediği için bunların çalıştırılabilen dosyalarda boşuna yer kaplamasına gerek de yoktur. PE ve ELF formatlarında bu bölümün yalnızca uzunluğu çalıştırılabilen dosya içerisinde tutulur. İşletim sisteminin yükleyicisi bu uzunluğa bakarak ".bss" bölümünü bellekte (RAM) tahsis eder ve orayı sıfırlar. (C ve C++’ta ilk değer verilmemiş global ve static yerel nesnelerini içerisinde 0 değeri bulunmaktadır. || bss alanının sıfırlanması henüz akış main fonksiyonuna girmeden derleyicilerin başlangıç kodları (startup codes) tarafından da yapılabilmektedir.)


İşletim Sisteminin Sistem Fonksiyonları ve Kapılar

3:17 AM
Korumalı modda çalışan Windows, Linux ve MacOS X gibi işletim sistemlerinde sıradan proseslerin kodları CPL = 3 önceliğinde çalışmaktadır. Bu kodlar işletim sisteminin yüksek öncelikle çalışması gereken sistem fonksiyonlarını kapılar yoluyla çağırırlar.



Böylece işletim sisteminin sistem fonksiyonları çalışırken kodun önceliği CPL = 0'a yükseltilmiş olur. Bu sürece "prosesin kullanıcı modundan çekirdek moduna geçmesi (user mode to kernel mode transition)" denilmektedir. Yani bu sistemlerde bizim programlarımız aslında sürekli olarak CPL = 3 ile kullanıcı modunda çalışmamaktadır. Sistem fonksiyonları ya da aygıt sürücülerdeki kodlar çağrıldığında programımızın öncelik seviyesi geçici olarak CPL = 0'a yükseltilmektedir. İşte kapılar Intel işlemcilerindeki bu geçişi sağlayan mekanizmalardır. Linux, BSD ve MacOS X sistemlerinde sistem fonksiyonları geleneksel olarak 80h kesmesi yoluyla çağrılmaktadır. (Yeni sistemler 64 bit Intel işlemcilerindeki SYSENTER ve SYSEXIT makine komutlarını da bu amaçla kullanabiliyorlar.) Bu 80h kesmesi bir tuzak kapısını tetikler. Bu kapı da kodun önceliğini CPL = 0’a çekerek kodun işletim sisteminin belirlediği bir noktaya aktarılmasını sağlar. İşte o noktada çağrılan sistem fonksiyonunun numarasına göre akış ilgili sistem fonksiyonun koduna aktarılmaktadır. Örneğin Linux sistemlerinde sistem fonksiyonu 80h kesmesi ile çağrılmadan önce onun numarası EAX yazmacına yerleştirilir. Böylece akış çekirdek moduna geçtiğinde buradaki kod EAX yazmacının değerine bakarak akışı uygun yere aktarır. Bu süreci aşağıdaki kodla temsil edebiliriz:

SYS_ENTER:     // kapıya girildiğinde akışın aktarıldığı yer. Artık kod için CPL = 0'dır
switch (eax) {
case 1:
sys_exit();
break;
case 2:
sys_fork();
break;
case 3:
sys_read();
break;
...
}

Tabii bu sözde kodu (pseudo code) yalnızca kafamızda bir fikir oluşsun diye verdik. Aslında Linux'ta uygun sistem fonksiyonuna dallanma işlemi EAX yazmacı switch içerisine sokularak değil bir diziye index yapılarak bir "look up" tablosu yoluyla gerçekleştirilmektedir. Yani bu sistemlerde sistem fonksiyonlarının adresleri bir dizide tutulmaktadır. Sistem fonksiyonlarının numarası da (EAX yazmacı içerisindeki değer) bu diziye indeks yapılarak dolaylı CALL işlemi ile çağrılmaktadır. Linux sistemleriyle BSD ve MacOS X arasında sistem fonksiyonlarının çağrılması arasında küçük bir farklılık vardır. Linux’ta sistem fonksiyonlarının parametreleri yazmaçlarla aktarılırken BSD ve MacOS X sistemlerinde (C’deki gibi) stack yoluyla aktarım yapılmaktadır. (Ayrıca Linux sistemlerindeki sistem fonksiyonlarının numaralarının ve parametrik yapılarının BSD ve MacOS X sistemleriyle bire bir aynı olduğunu da düşünmemelisiniz.) Windows sistemlerinde ise çekirdek moduna geçiş genel olarak 2EH kesmesiyle yapılmaktadır. Fakat genel mekanizma Linux, BSD ve Mac OS X sistemlerine oldukça benzemektedir.

Korumalı Mod Nedir?

Linux Boot Sequence

Korumalı mod proseslerin bir arada çalıştığı çok prosesli sistemlerde sistem güvenliğini artırmak için düşünülmüştür. Intel’in koruma mekanizmasında dört öncelik derecesi vardır. Ancak işletim sistemleri genellikle yalnızca iki dereceyi kullanmaktadır: 0 ve 3. Intel sisteminde düşük numara daha yüksek, yüksek numara ise daha düşük öncelik belirtmektedir.

  • 0 önceliğine "çekirdek modu (kernel mode)" önceliği, 
  • 3 önceliğine de "kullanıcı modu (user mode)" önceliği denilmektedir. 

32 bit Windows ve Linux gibi sistemler düz model (flat model) kullanmaktadır. Bu modelde tüm segment yazmaçlarının gösterdiği betimleyicilerin taban adresleri 0 ve limit değerleri de 4 GB’dir. Düz modelde segment tabanlı bir koruma uygulanmamaktadır. Yani bu modelde bir prosesin CS yazmacı dışındaki segment yazmaçlarının değerlerini değiştirmesi için bir gerekçe yoktur. Zaten düz model uygulayan sistemlerde genellikle tüm kullanıcı mod programları için tek bir kod ve data/stack betimleyicisi kullanılmaktadır. Bu betimleyicilerle de terorik olarak belleğin her yerine erişilebilmektedir. Korumalı modda o anda çalışmakta olan kodun öncelik derecesi CS yazmacının düşük anlamlı iki bitiyle belirlenmektedir. Bu bitlere CPL (Current Privilege Level) denir. Intel’de özel makine komutlarını ancak CPL değeri 0 olan kodlar kullanabilirler. Böylece sıradan prosesler CPL = 3 değeriyle çalıştıkları için bu makine komutlarını kullanamamaktadır. Ayrıca CPL değeri sayfalama mekanizması aktifken bellekte sayfalara erişirken de kontrol işlemlerine sokulmaktadır. Şöyle ki: Her sayfanın iki öncelik derecesi vardır. Önceliklerden birine "kullanıcı (user)", diğerine ise  "yönetici (supervisor)" önceliği denir. CPL değeri 1, 2 ve 3 olan kodlar ancak kullanıcı önceliğindeki sayfalara erişebilirler. CPL değeri 0 olan kodlar ise tüm sayfalara erişebilmektedir. İşletim sisteminin çekirdek kodları "yönetici (supervisor)" önceliğindeki sayfalarda tutulur. Böylece bu alanlara yalnızca işletim sisteminin kodları erişebilmektedir. 



Korumalı modda programcı DS, ES, SS, FS ve GS segment yazmaçlarındaki değerleri MOV komutlarıyla değiştirmek isterse bazı kontroller uygulanmaktadır. Özet olarak programcı CPL değerinden daha yüksek önceliğe sahip bir betimleyiciyi gösteren selektörü bu segment yazmaçlarına yükleyememektedir. Zaten yukarıda da ifade ettiğimiz gibi Windows, Linux gibi sistemler "düz bellek modeli (flat model)"  kullanmaktadır. Düz bellek modelinde de DS, ES, SS, FS ve GS segment yazmaçlarını yüklemek istemenin pratikte bir amacı yoktur. Korumalı modda çalışmakta olan kodun önceliğinin yükseltilmesi uzak CALL ve JMP işlemleriyle yapılamamaktadır. Bunu yapmanın tek yolu "kapı (gate)" denilen özel bir mekanizmayı kullanmaktır. Düşük öncelikli kodlar kapı ile belirtilen adresteki kodları yüksek öncelikle çalıştırabilmektedir.

API ve ABI Kavramları Üzerine

Yazılımların tüm mimarilerde çalışması ve geriye doğru uyumlu (backward compatibility) olması en çok istenen özelliklerdir. Geliştirilen yazılımın belirli bir dağıtım veya mimariye bağımlı olmayıp, taşınabilir olması büyük kolaylık sağlayacaktır. Sistem seviyesinden bakıldığında taşınabilirlikle ilgili 2 farklı özellik bulunması gerekir. Bunlar;
  • Application Programming Interface (API)
  • Application Binary Interface (ABI)
Şimdi sırasıyla bu kavramları inceleyelim;

ABI ( Application Binary Interface )

ABI, yazılım bileşenleri arasında belirli bir mimari için amaç dosyalar (object file) arasında arayüz  (interface) tanımlamaktadır. ABI demek ayrı ayrı derlenmiş modüllerin bir arada çalışabileceklerine dair alt seviyeli ve detaylı teknik kurallar bütünüdür. ABI uygulama bileşenleri arasında makine kodu seviyesinde uyumluluğu sağlar. Bu uyum korunduğu müddetçe aralarında etkileşim bulunan yazılım bileşenlerinin arka planı değişse de yeniden derlenmeye ihtiyaç duymaksızın eskisi gibi kulanmaya devam ederler.

  • Fonksiyonların nasıl çağrılacağı (calling convention), 
  • Parametrelerin nasıl geçirileceği, 
  • Yazmaçların kullanım şekilleri,
  • Sistem çağrılarının gerçekleştirilme biçimi, 
  • Amaç dosyaların bağlanması (linklenmesi), 
  • Amaç (object dosya) formatı gibi konular ABI kavramı içerisinde değerlendirilebilir. 
Yazılım geliştirme sürecinde ABI kavramı çok karşımıza çıkmaz. Kullanılan geliştirme araçları hedef platform için belirlenen ABI kurallarına uygun kod üretirler. Alt seviye işler yapanlar için bu genelleme doğru değildir. Sistem düzeyinde kod geliştirmek isteyenlerin üzerinde çalıştığı ve diğer çalışmasını istediği sistemlerin ABI standartlarını bilmesi gerekir.


API ( Application Program Interface )

API, uygulamaların kaynak kod seviyesinde birbirleriyle iletişim kurabilmelerine imkan sağlayan, önceden kararlaştırılmış arayüzler (interface) olarak tanımlanabilir. Genellikle her bir API, daha karmaşık ve alt seviye detaylar içeren bir sürecin, çeşitli arayüzlerle (fonksiyon çağrıları gibi) soyutlanmasını sağlar. Bu şekildeki bir soyutlama üzerinden kullanılan API'yi hizmet olarak veren yazılım bileşenleri güncellense ve alt tarafta yapılan işlemlerle ilgili yöntemler değiştirilmiş bile olsa, API seviyesinde aynı arayüz sağlandığı müddetçe bu API'yi kullanan uygulamalar için bir değişiklik yapılmasına gerek olmayacaktır.




Kısaca bir yazılımın, kullandığı kütüphanelerin,servislerin sonraki versiyonlarında herhangi bir değişikliğe gitmek zorunda kalmadan problemsiz çalışabilmesini sağlayan bir arayüz tanımlanması API kavramının ürünüdür.

Çevre Değişkenlerine Neden Gereksinim Duyulmaktadır

5:55 AM

Çevre değişklenlerine programlamadan da aşina olduğumuz işletim sistemi düzeyindeki global değişkenler gibi bakılabilir. Programlar birtakım dosyaları vs. bazı çevre değikenlerinin belirttiği yerde arayabilirler. Örneğin bir veritabanı dosyası DATABASE isimli bir çevre değişkeninin belirttiği dizinde aranabilir. Bu durumda programcı önce getenv 


fonksiyonuyla bu çevre değişkeninin değerini alır ve dosyayı o dizinde arayabilir. Veritabanı dosyası başka dizine yerleştirmek istenirse tek yapılacak şey bu çevre değişkeninin değerini değiştirmektir. Örneğin pek çok C derleyicisi <...> biçiminde include edilmiş dosyaları INCLUDE isimli bir çevre değişkenin belirttiği dizinde aramaktadır. Eğer bu çevre değişkeni set edilmemişse default bir dizin kullanılmaktadır. Ya da örneğin Java'da çeşitli jar dosyaları ve derlenmiş dosyalar CLASSPATH isimli bir çevre değişkenine bağlı olarak aranmaktadır. Bazı çevre değişkenlerini ise doğrudan işletim sistemi kullanmaktadır. (Örneğin PATH gibi, LD_LIBRARY_PATH gibi). 

Linux çevresel değişkenleri örneği


Windows çevresel değişkenleri örneği

Bazı çevre değişkenleri işletim sistemini hakkında bilgi vermektedir. Örneğin Windows hangi dizine yüklenmiştir? O anda kullanılan yerel ayarlar nelerdir? Kullanıcının ismi nedir? Home dizini hangisidir gibi bilgiler çevre değişkenleri aracılığıyla alınabilmektedir. Çevre değişkenleri proseslerarası haberleşmede de bazen kullanılabilmektedir. Örneğin, üst proses belli bir çevre değişkenini set ederek alt prosesi çalıştırır. Alt proses böylece o çevre değişkeninden bilgi alabilir. Böylesi basit bilgi aktarımı için herhangi bir proseslerarası haberleşme yönteminin kullanılmasına gerek kalmadan aktarılmış olur.


İşletim Sistemlerinin GUI Ortamlarında Mesaj Tabanlı Çalışma Modeli

2:31 AM ,
Mesaj tabanlı programlama modelinde klavye ve fare gibi aygıtlarda oluşan girdileri (event'leri) programcı kendisi almaya çalışmaz. Ya da pooling mekanizması gibi bir mekanizma ile girdinin oluşup oluşmadığını kontrol etmeye çalışmaz. Fare gibi, klavye gibi girdi aygıtlarını işletim sisteminin (ya da GUI alt sistemin) kendisi izler. Oluşan girdi olayı hangi pencereye ait ise işletim sistemi ya da GUI alt sistemi, bu girdi olayını “mesaj” adı altında bir yapıya dönüştürerek o pencerenin ilişkin olduğu (pencereyi yaratan) programın “mesaj kuyruğu (message queue)” denilen bir kuyuk sistemine yerleştirir. Mesaj kuyruğu içerisinde mesajların bulunduğu FIFO (First in First outprensibiyle çalışan bir kuyruk veri yapısıdır.  Sistemin daha iyi anlaşılması için süreci maddeler halinde özetleyelim:

  1. Her programın (ya da thread’in) “mesaj kuyruğu” denilen bir kuyruk veri yapısı vardır. Mesaj kuyruğu işletim sisteminin ya da GUI mekanizmasının bıraktığı mesajlardan oluşmaktadır.
  2. İşletim sistemi ya da GUI alt sistem gerçekleşen girdi olaylarını “mesaj (message)” adı altında bir yapı formatına dönüşürmekte ve bunu pencerenin ilişkin  olduğu programın (ya da thread’in) mesaj kuyruğuna eklemektedir.
  3. Mesajlar ilgili olayı betimleyen ve ona ilişkin bazı bilgileri barındıran yapı (structure) nesleridir. Örneğin Windows’ta mesajlar MSG isimli bir yapıyla temsil edilmişleridir. Bu yapının elemanlarında mesajın ne mesajı olduğu (yani hangi olaydan dolayı gönderildiği) ve olaya ilişkin gerekli bilgiler bulunur.

Görüldüğü gibi GUI programlama modelinde girdileri programcı elde etmeye çalışmamaktadır. Girdileri bizzat işletim sisteminin kendisi ya da GUI alt sistemi elde edip programcıya mesaj adı altında iletmektedir. GUI programlama modelinde işletim sisteminin (ya da GUI alt sistemin) oluşan mesajı ilgili programın (ya da thread’in) mesaj kuyruğuna eklemenin dışında başka bir sorumluluğu yoktur. Mesajların kuyruktan  alınarak işlenmesi ilgili programın sorumluluğundadır. Böylece GUI programcısının mesaj kuyruğuna bakarak sıradaki mesajı alması ve ona uygun işlemleri yapması gerekir. Bu modelde programcı kodunu şöyle düzenler: 
  • Bir döngü içerisinde sıradaki mesajı kuyruktan alma, 
  • Onun neden gönderildiğini belirleme,
  • Uygun işlemleri yapma, 
  • Kuyrukta mesaj yoksa da blokede bekleme
İşte GUI programlarındaki mesaj kuyruğundan mesajı alıp işleyen döngüye "mesaj döngüsü (message loop)" denilmektedir. Tipik bir GUI programında programcı bir döngü içerisinde mesaj kuyruğundan sıradaki mesajı alır ve işler. Mesajın işlenmesi ise “önce ne olmuş onu anlama ve ben buna karşı ne yapmalıyım?” biçiminde oluşturulmuş olan kodlarla yapılmaktadır. Pekiyi bir GUI programı nasıl sonlanmaktadır? İşte pencerenin sağındaki veya solundaki X (çarpı) simgesine kullanıcı tıkladığında işletim sistemi ya da GUI alt sistem bunu da bir mesaj olarak o pencerenin ilişkin olduğu prosesin (ya da thread’in) mesaj kuyruğuna bırakır. Programcı da kuyruktan bu mesajı alarak mesaj döngüsünden çıkar ve program sonlanır.


GUI ortamımız ister .NET, ister Java, ister MFC, isterse Qt olsun, işletim sisteminin ya da GUI alt sistemin çalışması hep burada açıklandığı biçimde gerçekleşir. Yani örneğin biz .NET'te ya da Java'da işlemlerin sanki başka biçimlerde yapıldığını düşünebiliriz. Aslında işlemler bu ortamlar tarafından aşağı seviyede yine burada anlatıldığı gibi yapılmaktadır. Sadece bize yalıtılmış bir ortam sunulmaktadır. Bu ortamlar (frameworks) ya da kütüphaneler çeşitli yükleri üzerimizden alarak bize daha rahat bir çalışma modeli sunarlar. Şimdi GUI programlama modelindeki mesaj kavramını biraz daha inceleyelim. Yukarıda da belirttiğimiz gibi bu modelde programcıyı ilgilendiren çeşitli olaylara mesaj denilmektedir. Örneğin klavyeden bir tuşa basılması, pencere üzerinde fare ile tıklanması, pencere içerisinde farenin hareket ettirilmesi gibi olaylar hep birer mesaj oluşturmaktadır. İşletim sistemleri ya da GUI alt sistemler mesajları birbirinden ayırmak için onlara birer numara karşılık verirler. Örneğin Windows’ta mesaj numaraları WM_XXX biçiminde sembolik sabitlerle kodlanmıştır. Programcılar da konuşurken ya da kod yazarken mesaj numaralarını değil, bu sembolik sabitleri kullanırlar. (Örneğin WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_KEYDOWN gibi) Mesajların numaraları yalnızca gerçekleşen olayın türünü belirtmektedir. Oysa bazı olaylarda gerçekleşen olaya ilişkin bazı bilgiler de söz konusudur. İşte bir mesaja ilişkin o mesaja özgü bazı parametrik bilgiler de işletim sistemi ya da GUI alt sistem tarafından mesajın bir parçası olarak mesajın içerisine kodlanmaktadır. Örneğin Windows’ta biz klavyeden bir tuşa bastığımızda Windows WM_KEYDOWN isimli mesajı programın mesaj kuyruğuna bırakır. Bu mesajı kuyruktan alan programcı mesaj numarasına bakarak klavyenin bir tuşuna basılmış olduğunu anlar. Fakat hangi tuşa basılmıştır? İşte Windows basılan tuşun bilgisini de ayrıca bu mesajın içerisine kodlamaktadır. Örneğin WM_LBUTTONDOWN mesajını Windows farenin sol tuşuna tıklandığında kuyruğa bırakır. Ayrıca basım koordinatını da mesaja ekler. Yani bir mesaj oluştuğunda yalnızca o mesajın hangi tür bir olay yüzünden oluştuğu bilgisini değil aynı zamanda o olayla ilgili bazı bilgileri de kuyruktaki mesajın içerisinden alınabilmektedir.

GUI programlama modelinde bir mesaj oluştuğunda o mesajın bir an evvel işlenmesi ve akışın çok bekletilmemesi gerekir. Aksi takdirde programcı kuyruktaki diğer mesajları işleyemez bu da “kullanıcı açısından program donmuş etkisi” yaratmaktadır. Eğer bir mesaj alındığında uzun süren bir işlem yapılmak isteniyorsa bir thread oluşturulup o işi o thread’e devretmek ve böylece mesaj döngüsünün işlemesini sağlamak gerekir. GUI programlama modellerinde genel olarak mesaj kavramı pencere kavramıyla ilişkilendirilmiştir. Yani bir pencere yaratılmadıktan sonra bir mesajın oluşma durumu da yoktur. Bu nedenle mesaj döngüsüne girmeden önce programcının en az bir pencere yaratmış olması gerekir. Windows gibi bazı sistemlerde pencereler thread’lerle ilişkilendirilmiştir. Bu sistemlerde prosesin tek bir mesaj kuyruğu yoktur. Her thread’in ayrı bir mesaj kuyruğu vardır. Bu durumda işletim sistemi ya da GUI alt sistem bir pencereye ilişkin bir işlem gerçekleştiğinde o pencerenin hangi prosesin thread’i tarafından yaratılmış olduğunu belirler ve mesajı o thread’in mesaj kuyruğuna bırakır. Böylece biz bir thread oluşturup o thread’te de bir pencere yaratmışsak artık bizim de o thread’te o pencerenin mesajlarını işlemek için mesaj döngüsü oluşturmamız gerekir. Tabii eğer thread’imizde biz hiçbir pencere oluşturmamışsak böyle bir mesaj döngüsünü oluşturmamıza da gerek yoktur. Örneğin Microsoft işletim sisteminde bir thread bir pencere yaratmışsa böyle thread’lere “GUI thread’ler” yaratmamışsa “worker thread’ler” denilmektedir.



İşletim Sistemlerinin GUI Alt Sistemlerine Genel Bakış

6:06 AM ,

Bilgisayar sistemlerine terminal ile bağlanılması 1957 yıllına denk gelmektedir. Bu yıldan itibaren programcılar bilgisayarlarla klavye ve ekran yoluyla doğrudan etkileşim içerisine girmeye başlamıştır. Programcılar bilgisayarlarla text tabanlı olarak etkileşim haline girmişlerdir. Bu tür text tabanlı ekranlara konsol (console) ekranları da denilmektedir. 80’li yılların başında IBM ilk kişisel bilgisayarları çıkarttığında DOS işletim sistemi grafik bir arayüze sahip değildi. Daha sonra Microsoft da Machintosh sistemleri gibi (Machintosh sistemleri ilk grafik arayüz kullanan sistemlerdir.) Windows sürümleriyle birlikte grafik arayüz kullanımına geçmiştir. UNIX dünyası da 80’li yılların sonlarına doğru yavaş yavaş grafik arayüzlerle tanışmıştır. UNIX/Linux sistemleri ağırlıklı olarak server sistemlerinde yaygın olarak  kullanılmaktadır. Server sistemlerinde de grafik arayüz genellikle -yavaşlatıcı bir etken oluşturduğu için- bulundurulmamaktadır. Ancak kişisel bilgisayara yüklenmiş olan UNIX/Linux sistemleri ağırlıklı olarak grafik arayüzlerle kullanılmaktadır. Eskiden konsol ekranlarında karakterler ekrana kalıp olarak basılıyordu. Zaten bu devirlerde ekranın kontrolünü sağlayan elektronik birimler şimdikilere göre ilkel düzeydeydi. Sonra ekran nokta temelinde kontrol edilebilmeye başlandı. Bugün ekrandaki görüntüyü oluşturan en küçük noktasal birime pixel (picture element) denilmektedir. Modern grafik kontrol kartları bu pixel'leri işleyip ekrana gönderme konusunda çok yetenek kazanmışlardır.


  • Windows sistemlerinin çekirdek (kernel) ile entegre edilmiş bir grafik sistemi vardır. Bu grafik sistem geliştirici düzeyinde GDI denilen bir API kütüphanesi ile kullanılıyordu. Hala bu kullanım devam etmektedir. Sonra Microsoft yine GDI üzerine GDI+ isimli bir kütüphane daha tasarlamıştır. .NET Form uygulamaları bu kütüphaneyi kullanmaktadır. Fakat Microsoft zaman içerisinde GDI’nin yavaş olduğunu gördüğü için pek çok katmandan geçmeden grafik işlemlerini daha çabuk yapan ve ismine “Direct X” denilen bir kütüphane daha geliştirmiştir. Direct X önceleri yalnızca oyun ve animasyon programcıları tarafından kullanılıyordu. Daha sonra Direct X'i kullanarak GUI elemanları oluşturan kütüphaneler GUI kütüphaneleri de ortaya çıkmıştır. Bununların en bilineni .NET dünyasında kullanılan WPF (Windows Presentation Foundation) ortamıdır.
  • UNIX/Linux sistemlerinde grafik çalışma çekirdek ile entegre edilmemiştir. Örneğin Linux çekirdeğinde grafik çalışmayla ilgili hiçbir kod yoktur. UNIX/Linux sistemlerinde temel grafik işlemler ayrı bir katman tarafından yapılmaktadır. Bu katmana X11 ya da yaygın ismiyle “X Window” denilmektedir. X Window sistemi client-server mantığıyla çalışan aşağı seviyeli bir katmandır. X Window çok temel pencere ve grafik işlemlerini yapmak için düşünülmüştür. Bu nedenle modern GUI uygulamaları için yetersizdir.  X Window sistemini doğrudan kullanabilmek için XLib denilen kütüphaneden faydalanılmaktadır. XLib’in daha modern XRC isimli bir versiyonu da vardır. Tıpkı Microsoft'un Direct-X alt kütüphanesi gibi UNIX/Linux dünyasında da daha hızlı grafik işlemler yapmak için "Open GL" denilen bir kütüphane de geliştirilmiştir. Open GL belli bir zamandan sonra "cross platform" olmuştur. Bu kütüphane Windows sistemlerinde de kullanılabilmektedir. Bazı "cross platform" GUI kütüphaneleri arka planda Open GL'den faydalanmaktadır.
  • Machintosh sistemleri 10 versiyonuyla birlikte UNIX türevi bir çekirdeğe geçmiştir. Mac OS X’in kernel kodları açıktır ve buna Darwin denilmektedir. (Darwin geniş ölçüde Free BSD ve Mach çekirdeğinin kodlarını bulunduruyor.) Mac OS X sistemlerinde grafik işlemler Cocoa denilen bir kütüphaneyle yürütülmektedir. Bu kütüphane Objective-C ve Swift dillerinden doğrudan kullanılabilmektedir. Cocoa'nın C’den kullanımı için Carbon isminde bir API grubu bulunmaktadır. Özetle bugünkü Mac sistemlerinde grafik işlemler çekirdeğin üzerine kurulmuş olan ve ismine "Cocoa" denilen bir katman kullanılarak yapılmaktadır.

GUI dünyasında cross platform kavramı ise "birden fazla işletim sisteminde aynı biçimde kullanılabilirliğini" ifade etmektedir. Örneğin Qt framework'ü Linux, BSD gibi UNIX türevi sistemlerde, Windows sistemlerinde ve Mac OS X sistemlerinde aynı biçimde kullanılan bir ortamdır. Ancak Qt yalnızca kaynak kod temelinde bir taşınabilirliğe sahiptir, çalıştırılabilen (executable) kod düzeyinde bir taşınabilirliğe sahip değildir. Yani biz bir platformda oluşturduğumuz çalıştırılabilir (executable) bir Qt dosyasını başka bir platforma götürerek çalıştıramayız. Fakat biz bir Qt projesini başka bir platforma götürüp orada derlersek uygulama aynı işlevsellikle çalışacaktır. Bu da geliştiricilerin her platform için başka bir ortam ya da kütüphane kullanma zorunluluğunu ortadan kaldırmaktadır. Qt "cross platform" luk özelliğini her sistemde o sisteme özgü altyapıyı kullanarak sağlamaktadır. Örneğin  UNIX/Linux sistemlerinde Qt doğrudan X Windows sistemini kullanarak işlevselliğini sağlamaktadır.


Mac OS X sistemlerinde ise Qt Cocoa alt yapısını kullanarak yazılmıştır.



Qt’nin Windows sürümünde ise “Direct X” alt yapısını kullanmaktadır.


Özetle işletim sistemlerinin GUI altyapısı bu şekildedir.


Ve Cross platform uygulama geliştirecek olanlar bu altyapıları kullanarak geliştirmelerini yapmak zorunda ya da bu amaca uygun geliştirilen framework'leri kullanması gerekmektedir.

Library, Toolkit ve Framework Kavramları

5:06 AM

Dilimizde de ingilizce'deki karşılıkları kullanılan "library", "toolkit" ve "framework" terimleri birbirlerine benzer kavramları belirtmektedir. “Library” yani kütüphane içerisinde derlenmiş kodların (hazır fonksiyonların) bulunduğu dosyalardır. Biz "library" içerisindeki fonksiyonları, sınıfları istediğimiz yerde kullanabiliriz. "Toolkit" terimi çoğu kez belli bir amaca yönelik "library" topluluğu olarak kullanılmaktadır. "Framework" kavramının pek çoklarına göre ayırıcı özelliği akış kontrolünün terslenmiş olması (inversion of control)  durumudur. Yani "framework"lerde yalnızca akış bizde değildir. Framework içerisindeki kodlar akış kontrolünü ele alır bazı olaylarda bizim kodlarımızı çağırırlar. Aşağıdaki resimde gösterildiği gibi bir manzara daha açıklayıcı olacaktır. Ayrıca "framework"ler pek çok yardımcı araca da sahip olabilmektedir.


Genel olarak "framework" kavramı daha büyük ve geniş kapsamlı bir organizasyon belirtmektedir. Bu üç kavramın herkes tarafından kabul edilen kesin sınırları çizilmiş tanımlarının olmadığını söyleyelim.



Örneğin Qt için "library" "toolkit" ve "framework" terimlerinin hepsi bir dönem kullanılmıştır. Bugün itibarıyla Qt’ye “framework” demek daha uygun gözükmektedir. Bir sistemin basitce framework olarak tanımlanabilmesi için şu özelliklerin bulunması gerekir:
  • Karmaşıklığın kullanıcıya daha basit biçimlerde gösterilmesi
  • Bazı gereksiz (hammaliye) işlemlerin kullanıcının üzerinden alınması
  • Kod akışının ele geçirilmesi ve duruma göre programcıya belli zamanlarda verilmesi
Halbuki kütüphanlerde bir akış ele geçirmek ve arka planda birtakım işlemleri bizim için yapmak gibi bir amaç yoktur. Programın akışı bizdedir. Biz istersek kütüphane fonksiyonlarını çağırırız. Onlar da faydalı işlemler yaparlar. Şüphesiz pek çok framework aynı zamanda birtakım kütüphanelere de (API'ler) sahiptir. Bazı ara durumlarda o şeyin framework mü yoksa kütüphane mi olarak adlandırılacağı konusunda tereddütler olabilir.

Sistem Programlama Nedir?

5:49 AM
Sistem programlama temel olarak, geliştiricilerin sistemle daha alt seviye bir katman üzerinden iletişim kurduğu dolayısıyla geliştirmelerin sisteme daha yakın bir noktada yapıldığı yazılım geliştirme modeline karşılık gelir. Sistem programları geliştirilirken kullanılan diller aşağı seviyeli olma eğilimindedir. Bunları yazmak için belli miktar teori ve mühendislik bilgisi gereklidir. Sistem programlama, yazılımın ağır sanayisi niteliğindedir. Bu nedenle ülkemizde bu alanda çalışan ve kendini geliştirmeye çalışan insan bulmak biraz sıkıntılı olmaktadır.



Tipik sistem programları şunlardır:

  •  İşletim Sistemleri
  •  Derleyiciler ve yorumlayıcılar
  •  Editörler
  •  Debug Programları
  •  Virüs ve Antivirüs yazılımları
  •  Haberleşme programları
  •  Gömülü sistem programları
  •  Aygıtların programlanması, aygıt sürücüler
  •  Veritabanı motorları
  •  Sanallaştırma yazılımları
  •  Oyun motorları
  •  ...

Sistem programlamadan günümüzde pratik olarak, yüksek seviyeli dillerde uygulama geliştirmek yerine (C#,Java, Ruby vb.) daha alt seviye diller yoluyla gerçekleştirilir. Sistem programlama faaliyetleri için en çok kullanılan diller C, C++ ve Sembolik Makine (spesifik ve performans gerektiren konular için makine dili gerekebilmektedir) dilleridir. İşletim sistemi çekirdeği ile standart C kütüphanesindeki fonksiyonlar ve sistem çağrıları yoluyla iletişim kurulmasını gerektirir. Sistem programlamanın daha alt seviyeli dillerde yapılıyor olması, bu konuda kazanılan deneyimlerin yüksek seviyeli dillerde işe yaramayacağı anlamına gelmez. Aksine alt seviyeyi bilmek pekiştirici bir etki yaratır. Bununla birlikte yüksek seviyeli bir dille çalışırken sistem programlama kısımları bizim için çoğunlukla görünmez veya zor görünür olur. Bu nedenle uğraştığımız alanlar veya karşılaşacağımız kavramlar üst seviye dillerde çalışanlar için çok anlam ifade etmeyecektir. Kısacası programlamanın ayrı bir dünyasına giriş yapıyoruz. Yarı yolda kalmamak dileğiyle hepimizi kolay gelsin.


write(0, "Hello, world!\n", 15);

ne kervan kaldı, ne at, hepsi silinip gitti
iyi insanlar iyi atlara binip gitti.

Yukarıda bahsi geçen, kıymetı pek bilinmeyen o güzel insanlardan arta kalan Anadolu'da, çöküşe doğru gidişin durdurulamadığı şu zamanlarda, bize düşen de bu değeri bilinmemiş insanları hatırlamak ve umudumuzu kaybetmemek olacaktır.

Tenekeci Mahmut Güzelgöz

Tanburi Cemil Bey

Urfa'dan Üç Musiki Ustası

Zaralı Halil Söyler


Maçkalı Hasan Tunç





Çekiç Ali

Benim de vefatından çok sonra nasıl kıymetli bir değere Televole kültürüyle yaklaştığımızı anladığım bizim için Ciguli resmi adıyla Angel Jordanov Kapsov.


Koskoca akordeon üstadını sadece Binnaz ile bilmek ayrı bir vasıfsızlık olsa gerek.



Son olarak Linux ve Windows üzerinde sistem programayla ilgili paylaşımlarımı buradan yapacağım.