1 Mart 2014 Cumartesi

Linux Sistem Programlama - Bölüm 1

Unix/Linux Sistemlerinin Tarihsel Gelisimi

Unix  1969-1970yıllarında  AT&T  Bell  Lab  tarafından  DEC-PDP  7  makinaları   için üretilmiştir.  Unix  projesinden önce AT&T MIT gibi üniversitelerle işbirliği yaparak MULTICS isimli bir işletim sistemi geliştirme projesinde çalışıyordu. Daha sonra grup çeşitli haklı gerekçelerle bu projeden çekilmiştir. Unix ismi B. Kernighan tarafından Multics sözcüğünden kelime oyunu yaparak uydurulmuştur. ilk Unix sistemi tamamen PDP makinalarının sembolik makine dilinde yazılmştı. Oyıllara kadar tüm işletim sistemleri zaten sembolik makine dilinde yazılıyordu. Unix işletim sistemi geliştirilirken Ken Thompson bir işletim sisteminin ciddi bir sistem olabilmesi için yüksek seviyeli bir derleyiciye sahip olması gerektiğini düşünüyordu.
Thompson, önceleri Fortran üzerinde durduysa da daha sonra BCPL gibi bir sistemin daha uygun olduğuna karar vermiştir. Bundan sonra Thompson BCPL'nin benzeri olan B dilinin tasarımında da çalşmştır. B bir yorumlayıcı sistemdi ve yavaş çalışıyordu. B programlama dili proje grubu tarafından yerel bir biçimde ve bazı sistem programlarında kullanılmştır. Proje grubu K.Thompson, D.Ritche, B.Kernighan gibi önemli kişilerden oluşuyordu. Grubun asıl amaçlarından biri Unix sistemini yüksek seviyeli bir dille yeniden yazmaktı. D.Ritche, B programlama dilini geliştirerek ilk kez 1971 yılında C programlama dilini tanımlamştir. 1973 yılında Unix işletim sistemi DEC-PDP 11 için çok büyük oranda C ile yeniden yazılmştır. Unix yüksek seviyeli bir programlama diliyle yazılmş olan ilk işletim sistemidir. Bu durum Unix işletim sisteminin farklı platfromlarda yazılmasını çok kolaylaştırmştır.  AT&T Unix işletim sisteminin kaynak kodlarını pekçok araştırma grubu ve üniversitelere dağıtmştır. Bu durum C programlama dilinin tanınmasına yol  açarken Unix sistemlerinin taşınabilirliğinin bozulması sonucunu da doğurmuştur. Çünkü kaynak kodları ele geçiren  kurumlar  orijinal Unix  sistemlerinde  değişiklikler  yaparak  farklı  Unix  sistemleri  oluşturmuşlardır.  Bu sistemlerin  en  önemlilerinden  biri  Berkeley  Sistemleridir, bu sistemler BSD (Berkeley software distrubition) olarak bilinmektedir.  BSD'nin FreeBSD, NetBSD ve OpenBSD biçiminde versiyonları vardır. AT&T kendi Unix sistemlerine de numara vermiştir. Örneğin, system III, systemV gibi...
Bugün Unix sistemlerinin en temel biçimi SVR4 (system 5 release 4 ) sürümüdür. Bundan sonra AT&T'nin çeşitli Unix sistemleri çıktıysa da, SVR4 bir standart anlatan özellik olmuştur.
80'li yıllarda pekçok özel firmada kendi Unix sistemlerini yazmaya başlamştır. Örneğin; Sun firmasının Solaris, HP firmasının HP-UX, SCO firmasının SCO_UNIX, IBM firmasının AIX örnek olarak verilebilir. 
AT&T  80  liyıllarının  başında  Unix  sistemlerine  telif  uygulamaya  başlamştır. Bu durumdan tedirgin olan üniversiteler ve araştırıcılar bedava Unix sistemleri geliştirme yönünde motive olmuşlardır. Bunun  üzerine  Hollandali profesor  A.  Tanenbaum işletim  sistemi derslerinde kullanmak üzere MINIX isminde mini bir Unix sistemi yazmştır. MINIX ticari amaçla çeşitli kesimler tarafından kullanılmş olsa da ciddi bir yaygınlık kazanmamştir. Fakat kaynak kodları pekçok geliştiriciye ilham vermiştir. 1985 yılında Richard Stallman FSF (Free  Software Foundation) isimli  bir  kurum  altında serbest  yazılım  fikrini atmştır.  Serbest  yazılım  bedava yazılımdan daha çok geliştirmede özgürlüğü  belirtmektedir.  Yani ,  programcı  yazdığı  programı  kaynak  koduyla  birlikte  verir, kaynak  kodu  sahiplenip  değişti rilmesini  engelleyemez.  Kaynak  kodu  elde  eden  programcı orijinal  yazardan alıntı yaptığını belirterek  kodu  değiştirebilir.  Serbest  yazılım  bedava olabilirde  olmayabilir de,  fakat  serbest  yazılım  parayla  satılsa  bile  kaynak  kodu  verilmek zorundadır.  Richard  Stallman  FSF  kurumunu  oluşturduktan  sonra  GNU  isimli  bir  proje oluşturmuştur.  GNU  (GNU’  not  UNIX)  bir işletim  sistemi  ve  yardımcı  ek  programlar oluşturmayı  hedefleyen  bir  projedir.  Bu  proje  hala  devam  etmektedir (www.fsf.org).  GNU projesi  kapsamında  pek çok  yararlı  programlar  yazılmştır (gcc  derleyicisi ). Ancak  maalesef işletim sisteminin kendisi  yazılamamştır. 
1990 yılında  Linus  Torvalds  GNU  lisansı  altında  MINIX  ve  UNIX  sistemlerinden  alıntılarla serbest  bir  Unix  sistemi  oluşturmuştur.  Bugün  Linux  sistemlerindeki  yazılımlar GNU  lisanslı yazılımlardır.  Yani,  Linux  sistemleri  çekirdeği  Linus  Torvalds  tarafından  tasarlanmş  olan yaralı programları GNU projesi kapsamıyla elde edilmiş olan bir sistemdir. Pekçok kişi bugün kullanılan bu sisteme Linux yerine GNU/Linux  denmesinin  daha  uygun  olacağını düşünmektedir. 
1980'li yılların sonlarına doğru UNIX sistemleri standart hale getirilmeye çalışılmştır. Bunun için IEEE bünyesinde stadardizasyon ekibi kurulmuş ve POSIX standartları diye bilinen standartlar oluşturulmuştur. POSIX bir grup standartlardan oluşan bir standartlar topluluğudur. Bu grup  içerisindeki herbir standart POSIX 1003.X  biçiminde isimlendirilmiştir. Örneğin,  1003.1  POSIX uyumlu  UNIX  sistemlerinin C'de  bulundurması gereken sistem fonksiyonlarına  ayrılmştır.  1003.2 Shell programlarının  kullandığı  standart komutları  tanımlamaktadır.

(Bu yazının tarihsel gelişim bölümü C ve sistem programcıları derneğinin Unix/Linux sistem programlama dökümanının giriş ksımından aynen kopyalanmıştır. Dökümana buradan erişim sağlayabilirsiniz.)

Giriş

Sistem fonksiyonları user mod'da uygulamayı donanıma en yakın yapan fonksiyonlardır.
Sistem çekirdeği içerisinde 2 türlü programlama yapilir.
  • Kernel modülü yazmak
  • Kernel yapısını degiştirerek yeniden kerneli derlemek

Standat C fonksiyonlari, POSIX fonksiyonlari, Sistem fonksiyonları

  • Standat C fonksiyonları bütün C derleyicilerinde olmasi gereken fonksiyonlardır ve bu fonksiyonlar en alt seviyeli fonksiyonlardir. 
  • POSIX fonksiyonlarıda butun POSIX sistemlerde var olan fonksiyonlardır ve bütün Unix/Linux sistemler icin kullanilabilir fonksiyonlardır. 
  • Sistem fonksiyonlari da biraz daha sisteme ozellestirilmis fonksiyonlardir.
Yazılımda genel olarak kod tekrarı istenmez. Cünkü kod tekrarı hem fazla yer kaplar hemde bakımı zordur. Bu nedenle yazılım sistemleri katman katman oluşturulur. Yani yeni bir katman başka bir katmanın var olduğu fikriyle oradaki fonksiyonlari cağırarak yapılır. Yazılımsal olarak en asağı katman işletim sisteminin dış dünyaya sunduğu aşagi seviyeli sistem fonksiyonlaridır.  

Örnek bir C kodu:

void add(a, b)
{
    return a+b;
}

int main(void)
{
    int a=10, b=20, c;
    c = add(a,b);
    ...    
}

Bu C kodunun Assembler karşılığı;

main proc near:
    push ebp
    mov ebp, esp
    sub ebp,12
    mov [ebp-4], 10
    mov [ebp-8], 20
    mov eax,[ebp-4]
    push ecx
    mov

Fakat sistem fonksiyonları isim ve parametrik yapı bakımından sistemden sisteme değisir. Hatta versiyondan versiyona bile değisir. Bunun yerine sistem fonksiyonalrını cağiran daha taşınabilir fonksiyon katmanı bulunmaktadır. Buna windows dünyasinda Windows API fonksiyonları, Unix/Linux dunyasinda POSIX fonksiyonları denilmektedir. 
POSIX fonksiyonları yalnızca linux sistemlerinde bulunmaktadir. Windows sistemlerde bulunmamaktadır.  Standart C fonksiyonları ise tum C derleyicilerinde bulunmaktadır. Java gibi .NET gibi QT gibi pekcok platfrom ve kütüphane kendi dünyasinda daha yüksek seviyeli ve taşınabilir fonksiyonlar ve sınıflar bulundurmaktadırlar.
Bazı POSIX fonksiyonları doğrudan bir sistem fonksiyonunu cağırmaktadir. Bazıları ise birden fazla sistem fonksiyonunu cagirir, bazıları ise hiçbir sistem fonksiyonunu cağırmayabilir. Bu durum Windows API fonksiyonları için de geçerlidir.
Linux sistemlerde trapgate mekaniması için aşağıdaki link bağlantıları faydalı olabilir.
  • http://stackoverflow.com/questions/15168822/intel-x86-vs-x64-interrupt-call
  • http://stackoverflow.com/questions/9111039/for-signal-in-linux-who-calls-int-0x80

İşlemcilerin Sunduğu Koruma Mekanizması

Koruma mekanizması bir processin zararli etkilerinden diğer procesleri ve isletim sistemini korumak icin olusturulmus bir mekanizmadır. Birinci elden işlemci tarafından uygulanır.
Koruma mekanizmasının iki yönü vardır;
  • bellek korumasi 
  • komut korumasi
Bellek koruması; bir processin kendi sınırlarının dışına erişip erişmediğini denetler. Komut koruması ise sistemi çökertecek komutların kullanılmasını yasaklamaktadir. Bu koruma mekanizmaları işletim sisteminin kullanıcı moduna (user modda) geçerli korumalardır.
Prosesler kernel ve user mod olmak üzere iki moddan birinde çalışır. Normal programlar user modda çalıştırılırlar. İşletim sisteminin kodlari ve aygıt sürücüler kernel modda çalışırlar. Kernel modda ise koruma mekanizmasi uygulanmaz. Hersey yapilabilmektedir.
Bir proses sürekli user modda kalmayabilir. Bir sistem fonksiyonu cağırıldığında proses user moddan gecici olarak kernel moda gecer. Sistem fonksiyonu kernel modda çalıştırılır. Sonra yeniden user moda geri dönülür.

Unix/Linux Sistemlerde Prosesler

Çalışmakta olan programlara proses denir. Her prosesin kernel alanı içerisinde oluşturulmuş olan bir process kontrol bloğu vardır. Tipik olarak process kontrol bloğu'nun icinde şu bilgiler bulunur.
  • Processin yetkilendirme bilgileri 
  • Processin ID'si
  • Processin bellek alanının nerede olduğu
  • Processin erişim hakları
  • Processin çalisma dizini
  • Processin açmis olduğu dosyalar
  • Processin istatistiksel bilgileri (örneğin process yaşamının ne kadarını kernel, ne kadarını user modda geçirmiştir)
  • Processin kesilme sırasındaki yazmaç (register) bilgileri
  • Processin Thread'leri hakkında bilgiler
  • .....

---------------

  • Bir process oluşturulurken, user modda oluşturulan hafıza alanının yanısıra bir de kernel alanı icerisinde (kernel stack) de bir alan ayırılır.
  • lxr.linux.no : linux kaynak kodlarını görebilecegimiz bir navigator. Versiyonlar arasında karşılaştırma da yapabilmektedir.
  • Linux sistemlerde kullanılan sistem çağrılarını http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html linkinden görebiliriz.

Linux sistemlerde proses kontrol bloğu task_struct ile temsil edilmektdir. Proses kontrol bloğu dallı budaklı bir yapı biçiminde olabilir. Yani, bazı büyük bilgiler ayrı veri yapılarındadırlar. Proses konrtol bloğundan oralar (büyük veri alanları) göstericiler ile gösterilmektedir. Bir bilginin process kontrol blogunda olmasi demek ona proses kontrol blığu ile erişilebiliyor demekdir. 

Not : proc dosya sisteminde procese ait bilgi silinir ise processi ps komutundan gizleyebiliriz 
Not : Windows ile ilgili dokümante edilmemiş bazı yapıları reactos.org adresinden görebilir ve inceleyebiliriz. Windows'da EPROCESS yapısı ile process kontrol blok tanımlanabilir. Bu yapı içerisinde PEB tanımlanmıştır. 

Linux'da threadler'i processler gibi yapmislar. Kendi proses kontrol bloğu bulunmaktadır. 
Unix/Linux sistemlerinde her prosesin sistem genelinde tek olan bir ID değeri vardır. Prosesler arasıda altlık/üstlük (parent/child) ilişkisi söz konusudur. Her proses başka bir proses tarafından yaratılır. Örneğin UNIX/Linux sistemlerindeki komut satırı da aslında bir programdır. Yani bir processdir (/bin/bash).

Sistem Boot Edildiğinde Proseslerin Durumu Nedir?

Bootdan gelen akış ilk prosesi oluşturur. Buna swapper yada pager denilmektedir ve bu prosesin ID degeri 0'dir. Bu proses init denilen prosesi yaratır ve artık swapper birşey yapmadan arka planda bekler. Sonra bir dizi olaylar sırasında akış shell'e kadar gelir. 

Kernel kendini yükledikten sonra try_to_run_init_process fonksiyonu ile baslangıç prosesini çalıştırır.

İşletim sistemi aslında bir kod yığınının hazırda beklemesidir.

Proses'in UserID ve GroupID Değerleri

Her prosesin proses kontrol bloğunda saklanan UserId ve GroupID degerleri vardır. UserId ve GroupId değerleri birer sayı olmasına karşın bunlara birer yazı da karşılık düşürülmüştür. Kernel işlemlerini bu isimlerin sayısal değerleri ile gerçeklestirmektedir. Ancak kullanıcı ve grup isimleri daha akılda kalıcıdır. 
Geleneksel olarak UserID'nin isimsel karşılığı /etc/passwd dosyasında GroupID'nin ise isimsel karşılığı /etc/group dosyasında tutulmalıdır. 
Aynı zamanda her prosesin effective UserID (etkin kullanici id'si) ve effective GrupID değeri de vardır. Normalde UserID ile etkin UserID, GrupID ile etkin GroupID aynı değerdedir. Fakat bazı seyrek durumlarda bunlar farklılaşabilmektedir. Fakat test işlemini her zaman etkin UserID ve etkin GrupID sokulur. 
Processin UserID, GrupID,etkin UserID,etkin GrupID değerleri proses yaratılırken üst prosesden aktarılır. Biz shell'den bir program çalıştırdığımızda shell'de bir process olduğuna gore çalıştırdığımız prosesin UserID ve GroupID değerleri shell'inki ile aynı olur. 

Shell üzerinden "id" isimli komut o anda shell processinin etkin UserID ve etkin GroupID değerlerini bize verir. 

Biz xWindow sistemi veya terminal yolu ile sisteme giriş yaptığımızda ilk UserID ve GroupID nasıl oluşturulmaktadır?

Işte bize, sisteme login olunurken bir kullanıcı ve parola sorulur. Dogrulama yapılır ve /etc/passwd'de gösterilen bir program bu user ve group id ile calistirilir. 

Uygulamanin calisma sirasi su sekilde  boot |---> Kernel |---> init |--->  tty  |--->  login

0 numarali user id değerine sahip prosese süper proses yada root prosesi denilmektedir. Pekcok linux dağıtımında işin başında ismi root olan ve userId değeri 0 olan bir kullanıcı da /etc/passwd dosyasında yaratılmıştır. 
Aslında /etc/passwd dosyasının kendisi, init programı ve login programı kernel kodlarına dahil değildir. Fakat kernel kodları prosesin etkin kullanıcı ve grup id'lerine bakacak şekilde yazılmıştır. Biz /etc/passwd dosyasını silersek login programı calıştığında bu dosyanın ici boş olduğu icin giriş işlemi yapılamayacaktır.

Prosesin UserID ve GroupId Değerlerinin Anlamı

Processin UserId ve GrupId'si buyuk ölçüde dosya sistemlerine ilişkin teste sokulurlar. Unix/Linux sistemlerinde bir dosyanın açılması ve yaratılması işlemleri yalnızca open isimli POSIX fonksiyonu ile yapılmaktadır. Bu fonksiyon linuxda sys_open fonksiyonunu cağırmaktadır.  
Glibc kütüphanesinin kaynak kodu içerisinde POSIX fonksiyonlarının kaynak kodları bulunmaktadır. 
Unix/Linux sistemlerinde her dosyanın user/group id değerleri vardir. Bir dosyanın userId'si o dosyayi yaratan prosesin yani open fonksiyonunu cağıran processin etkin user id'si olarak alınır. Dosyanın grup id değeri ise sistemden sisteme değişebilecek biçimde iki seçenekten birisi olabilir. 
  1. Dosyayı yaratan prosesin etkin GrupID'si olarak
  2. Dosyanın içinde yaratıldığı dizinin etkin GrorpID'si olarak 
Linux'da default durum dosyanın group id'sinin onu yaratan processin etkin group idsi biçiminde alınmasıdır. Fakat bu durum çesitli koşullarda değiştirilebilmektedir.


Hiç yorum yok:

Yorum Gönder