İşletim Sistemleri: Süreç, Bellek, Dosya ve Giriş Çıkış

İşletim Sistemleri: Süreç, Bellek, Dosya ve Giriş Çıkış

İşletim sistemi yapısı, süreç ve iş parçacıkları, CPU zamanlama, eşzamanlılık, deadlock, sanal bellek, dosya sistemi, giriş çıkış ve koruma mekanizmalarını bir araya getiren ders notları.

İşletim sistemleri notlarım süreç, bellek ve giriş-çıkışın birbirinden bağımsız başlıklar olmadığını anlamaya odaklanıyordu. İlk sürümdeki çekirdek kavramları korudum. Sonraki teknik gözden geçirmelerde thread, sanal bellek, dosya sistemi ve koruma konularındaki terminolojiyi güncelledim; yeni kavramları eski dönemin parçası gibi göstermemeye dikkat ettim.

Ünite 1: İşletim Sistemlerine Giriş

İşletim sisteminin temel görevi

Bir bilgisayar sistemi işlemci, ana bellek, kalıcı depolama ve giriş/çıkış aygıtlarından oluşur. Bu kaynakları doğrudan uygulamaların yönetmesi hem güç hem de güvenli değildir. İşletim sistemi, donanım ile uygulamalar arasında çalışan temel yazılım katmanıdır.

İşletim sisteminin iki ana görevi vardır:

  • Donanım ayrıntılarını soyutlamak.
  • Sınırlı sistem kaynaklarını programlar arasında yönetmek.

Bir uygulama dosyadan veri okumak istediğinde diskin veya SSD'nin fiziksel çalışma ayrıntılarını bilmez. İşletim sistemine bir okuma isteği gönderir. İşletim sistemi bu mantıksal isteği dosya sistemi, önbellek, blok katmanı ve aygıt sürücüsü üzerinden fiziksel işleme dönüştürür.

Bu nedenle işletim sistemi yalnızca bir donanım denetleyicisi değildir. Aynı zamanda programlara düzenli ve güvenli bir çalışma ortamı sunan bir soyutlama katmanıdır.

Kaynak yönetimi

İşlemci zamanı, ana bellek, depolama alanı ve giriş/çıkış aygıtları sınırlı kaynaklardır. Birden fazla program çalıştığında bu kaynaklar paylaşılmalıdır.

İşletim sistemi bu paylaşım sırasında birkaç amacı birlikte gözetir:

  • işlemcinin boş kalmaması,
  • görevlerin makul sürede tamamlanması,
  • etkileşimli uygulamaların hızlı yanıt vermesi,
  • görevlerin birbirinin belleğini bozmaması,
  • depolama ve G/Ç kaynaklarının verimli kullanılması,
  • yetkisiz erişimin engellenmesi,
  • sistemin hata durumlarında bütünlüğünü koruması.

Bu amaçlar her zaman aynı yönde değildir. Örneğin toplam sistem verimini artıran bir planlama yöntemi tek bir görevin bekleme süresini uzatabilir. İşletim sistemi tasarımı büyük ölçüde bu tür ödünleşimlerin yönetimidir.

Bilgisayar sisteminin temel modeli

İşletim sistemi açısından basitleştirilmiş bir bilgisayar sistemi üç ana bileşenle ele alınabilir:

  1. işlemci,
  2. ana bellek,
  3. giriş/çıkış sistemi.

Bu bileşenler veri, adres ve denetim yolları veya güncel sistemlerde bunların daha gelişmiş karşılıkları üzerinden iletişim kurar.

Adres yolu, erişilecek bellek veya aygıt konumunu belirler.

Veri yolu, işlemci, bellek ve aygıtlar arasında veriyi taşır.

Denetim yolu, okuma, yazma, kesilme ve zamanlama gibi işlemleri belirleyen sinyalleri taşır.

Modern sistemlerde fiziksel bağlantı mimarileri çok daha karmaşıktır. PCI Express, bellek denetleyicileri, NUMA topolojileri ve yüksek hızlı çevre birimi bağlantıları klasik ortak yol modelinden farklıdır. Buna rağmen adres, veri ve denetim ayrımı işletim sistemi kavramlarını anlamak için geçerli bir soyutlamadır.

Komutların işletimi

Von Neumann modelinde program komutları ve veriler bellekte tutulur. İşlemci temel olarak şu çevrimi tekrarlar:

  1. komutu bellekten getirir,
  2. komutu çözer,
  3. gerekli veriyi elde eder,
  4. işlemi gerçekleştirir,
  5. sonucu yazar,
  6. bir sonraki komuta geçer.

Bu yapı genellikle fetch-decode-execute çevrimi olarak ifade edilir.

Bir bellek veya aygıt erişiminin doğru zamanda gerçekleşmesi gerekir. Donanım düzeyindeki bu zaman ilişkileri zaman çizelgeleri ile gösterilebilir. İşletim sistemi açısından önemli olan ayrıntı, işlemci ile çevre birimlerinin aynı hızda çalışmamasıdır.

İş kavramı

Bir kullanıcının bilgisayar sistemine bir bütün olarak yaptırmak istediği işlem kümesine , yani job denir.

Bir iş tek programdan oluşabilir. Birden fazla programın belirli sırada çalıştırılması da tek iş olarak değerlendirilebilir.

Örneğin:

  1. kaynak kodun derlenmesi,
  2. bağlanması,
  3. testlerin çalıştırılması,
  4. sonuçların dosyaya yazılması

tek bir iş akışını oluşturabilir.

Günümüzde shell script, build pipeline, batch job ve CI/CD job gibi yapılar aynı temel düşüncenin farklı uygulamalarıdır.

Tek iş ve çok iş düzeni

Bir sistem aynı anda yalnızca bir işi işletime alıyorsa tek iş düzeni vardır.

Bu yaklaşım basittir ancak kaynakları verimsiz kullanır. Çalışan program yavaş bir G/Ç işlemini beklediğinde işlemci de boş kalabilir.

Birden fazla işin işletimi üst üste bindirildiğinde çok iş düzeni, klasik adıyla multiprogramming ortaya çıkar.

Bir görev G/Ç beklerken işlemci başka bir göreve verilebilir. Böylece işlemci ile G/Ç aygıtlarının çalışma süreleri örtüştürülür.

Temel düşünce şudur:

Bir görevin bekleme süresi başka bir görevin çalışma süresine dönüştürülür.

Bu yaklaşım modern çok görevli işletim sistemlerinin temelidir.

Program ve görev

Program, çalıştırılabilir komutlardan oluşan durağan bir yapıdır.

Görev, güncel terminolojiyle süreç veya process, çalışan program örneğidir.

Aynı programın aynı anda çalışan iki örneği iki ayrı süreçtir. Kodları aynı olabilir ancak çalışma durumları farklıdır.

Bir süreç için işletim sistemi en azından şu bilgileri tutar:

  • süreç kimliği,
  • işlemci yazmaçları,
  • program sayacı,
  • yığıt bilgileri,
  • adres alanı,
  • açık dosyalar,
  • kullanıcı ve yetki bilgileri,
  • planlama bilgileri,
  • çalışma durumu.

Bu bilgiler süreç denetim bloğu, yani PCB - Process Control Block benzeri veri yapılarında tutulur.

Çok görevli çalışma

İşlemci çekirdeği aynı anda yalnızca bir komut akışını çalıştırabilir. Buna rağmen birçok süreç aynı anda ilerliyormuş gibi görünür.

İşletim sistemi işlemciyi kısa sürelerle görevler arasında değiştirir. Bu işlem yeterince hızlı olduğunda kullanıcı görevlerin eşzamanlı çalıştığını algılar.

Çok çekirdekli sistemlerde gerçek paralellik de mümkündür. Örneğin dört çekirdekli bir işlemci dört farklı komut akışını gerçekten aynı anda çalıştırabilir.

Bu nedenle iki kavram ayrılmalıdır:

Concurrency, birden fazla işin zaman bakımından örtüşerek ilerlemesidir.

Parallelism, birden fazla işin fiziksel olarak aynı anda çalışmasıdır.

Toplu işlem

Toplu işlem, kullanıcının işletim sırasında doğrudan müdahalesine ihtiyaç duymayan işlerin sıraya alınarak çalıştırılmasıdır.

Geçmişte işler fiziksel olarak biriktirilip sisteme topluca verilirdi. Günümüzde aynı kavram zamanlanmış görevlerde, veri işleme sistemlerinde, render işlerinde, yedeklemede ve büyük hesaplama kümelerinde yaşamaktadır.

Toplu işlemin güçlü yönü yüksek kaynak verimidir. Zayıf yönü ise doğrudan kullanıcı etkileşiminin düşük olmasıdır.

Etkileşimli işlem

Etkileşimli sistemde kullanıcı yaptığı işlemin sonucunu kısa sürede görmek ister.

Komut kabukları, masaüstü uygulamaları, editörler ve çevrim içi terminaller bu sınıfa girer.

Burada kritik ölçüt toplam tamamlanma süresinden çok yanıt süresidir.

Zaman paylaşımlı işletim sistemleri işlemciyi küçük zaman dilimleri halinde süreçler arasında paylaştırarak birçok kullanıcıya sistem kendisine aitmiş gibi bir çalışma ortamı sağlayabilir.

Gerçek zamanlı işlem

Gerçek zamanlı sistemde yalnızca doğru sonuç üretmek yeterli değildir. Sonucun belirli bir zaman sınırı içinde üretilmesi gerekir.

Bu sınır deadline olarak adlandırılır.

Gerçek zamanlı sistemler iki temel grupta düşünülür.

Hard real-time sistemde zaman sınırının aşılması sistem başarısızlığı anlamına gelebilir.

Soft real-time sistemde zaman sınırının aşılması istenmez ancak tek başına sistem başarısızlığı sayılmaz.

Endüstriyel kontrol, uçuş kontrolü, otomotiv sistemleri ve kimi haberleşme sistemleri gerçek zamanlı çalışma gerektirebilir.

Gerçek zamanlı olmak ile hızlı olmak aynı şey değildir. Temel ölçüt ortalama hız değil, zaman davranışının öngörülebilir olmasıdır.

İşletim sisteminin temel kesimleri

Genel amaçlı bir işletim sistemi şu temel işlevleri yerine getirir:

  • süreç ve thread yönetimi,
  • işlemci planlama,
  • ana bellek yönetimi,
  • sanal bellek yönetimi,
  • giriş/çıkış yönetimi,
  • dosya sistemi yönetimi,
  • aygıt sürücülerinin yönetimi,
  • ağ iletişimi,
  • koruma ve güvenlik,
  • kullanıcı ve yetki yönetimi.

Bu kesimler birbirinden bağımsız değildir. Bir dosya okuma işlemi aynı anda süreç yönetimi, bellek yönetimi, dosya sistemi, blok G/Ç ve aygıt sürücüsü katmanlarını ilgilendirebilir.

Çekirdek ve kullanıcı alanı

Modern işletim sistemleri ayrıcalıklı işlemleri kullanıcı programlarından ayırır.

Kernel space, işletim sisteminin çekirdek bileşenlerinin çalıştığı ayrıcalıklı alandır.

User space, sıradan uygulamaların çalıştığı daha sınırlı alandır.

Kullanıcı programı doğrudan kritik donanım kaynaklarını değiştiremez. Gerektiğinde işletim sisteminden hizmet ister.

Bu ayrım sistem bütünlüğünün temel koruma mekanizmalarından biridir.

Sistem çağrıları

Kullanıcı programının çekirdekten hizmet istemesine olanak veren denetimli arayüze sistem çağrısı denir.

Tipik sistem çağrıları şunlarla ilgilidir:

  • dosya açma,
  • veri okuma ve yazma,
  • süreç oluşturma,
  • süreç sonlandırma,
  • bellek eşleme,
  • ağ bağlantısı oluşturma,
  • aygıt işlemleri.

Unix benzeri sistemlerde open(), read(), write(), fork(), exec() ve mmap() bunun bilinen örnekleridir.

Sistem çağrısı sırasında işlemci kontrollü biçimde kullanıcı modundan çekirdek moduna geçer. İşlem tamamlandığında kullanıcı moduna döner.

Bu mekanizma işletim sisteminin sunduğu soyutlama ile donanımsal koruma arasında köprü oluşturur.

İşletim sistemlerinin evrimi

İlk sistemler tek programlı ve donanıma yakın yapılardı. Daha sonra toplu işletim, çok programlama ve zaman paylaşımı ortaya çıktı.

Gelişim çizgisi daha sonra şu yönlerde ilerledi:

  • çok kullanıcılı sistemler,
  • çok işlemcili sistemler,
  • kişisel bilgisayarlar,
  • ağ işletim sistemleri,
  • sanallaştırma,
  • çok çekirdekli işlemciler,
  • mobil sistemler,
  • konteyner tabanlı çalışma ortamları,
  • dağıtık altyapılar.

Teknoloji değişse de işletim sisteminin temel sorusu değişmemiştir:

Sınırlı fiziksel kaynaklar, birden fazla yazılım bileşenine nasıl güvenli ve verimli biçimde sunulur?

Ünite 2: Giriş/Çıkış Sistemi

Giriş/çıkış sisteminin amacı

İşlemciler ve bellek çok hızlıdır. Çevre birimleri ise farklı hız, protokol ve veri aktarım özelliklerine sahiptir.

İşletim sisteminin G/Ç sistemi bu farklılıkları soyutlar.

Bir uygulama açısından:

oku
yaz
gönder
al

gibi birkaç mantıksal işlem yeterlidir.

Fiziksel düzeyde ise aynı işlem aygıt yazmaçlarının programlanmasını, kesilme yönetimini, DMA aktarımını, hata denetimini ve tampon kullanımını gerektirebilir.

Aygıt, denetleyici ve arabirim

Fiziksel aygıt ile işlemci arasında genellikle bir denetleyici bulunur.

Denetleyici şu tür yazmaçlara sahip olabilir:

  • veri yazmacı,
  • durum yazmacı,
  • komut yazmacı,
  • denetim yazmacı.

İşlemci veya aygıt sürücüsü bu yazmaçlar üzerinden donanımla haberleşir.

Modern donanımlarda aygıt yazmaçları çoğunlukla belleğe eşlenmiş G/Ç, yani MMIO - Memory-Mapped I/O üzerinden erişilebilir.

Seri ve paralel iletişim

Klasik G/Ç anlatımında seri ve paralel iletişim önemli bir ayrımdır.

Seri iletişimde bitler aynı fiziksel kanal üzerinden ardışık aktarılır.

Paralel iletişimde birden fazla bit aynı anda farklı hatlardan aktarılır.

Geçmişte paralel arabirimler kısa mesafelerde yaygındı. Yüksek hızlı modern sistemlerde seri bağlantılar baskındır. PCI Express, USB, SATA ve yüksek hızlı ağ bağlantıları seri fiziksel aktarım tekniklerinden yararlanır.

Eski RS-232 ve Centronics ayrıntıları tarihsel önem taşır. Güncel işletim sistemi açısından kalıcı olan kavram protokolün kendisi değil, farklı fiziksel aygıtların ortak bir G/Ç soyutlamasına bağlanmasıdır.

Zamanuyumlu ve zamanuyumsuz iletişim

Zamanuyumlu iletişimde taraflar ortak veya geri kazanılabilir bir zamanlama düzenine göre veri aktarır.

Zamanuyumsuz iletişimde veri aktarımının sınırlarını belirlemek için ek işaretleme mekanizmaları gerekir.

Bu ayrım yalnız fiziksel haberleşmede değil, yazılım G/Ç tasarımında da önemlidir.

Programın G/Ç işlemi tamamlanıncaya kadar beklemesi synchronous I/O olarak düşünülebilir.

İşlem başlatıldıktan sonra programın başka iş yapabilmesi ise asynchronous I/O yaklaşımına karşılık gelir.

Seçmeli G/Ç ve polling

En basit G/Ç yönteminde işlemci aygıtın durum yazmacını sürekli denetler.

Bu yöntem polling veya programlı G/Ç olarak bilinir.

Basitleştirilmiş akış şöyledir:

while aygıt_hazır_değil:
    durumu_kontrol_et

veriyi_aktar

Yöntem basittir ancak işlemci zamanı tüketir.

Aygıt uzun süre hazır olmayacaksa işlemci milyonlarca kez aynı durumu kontrol edebilir.

Polling tamamen gereksiz değildir. Çok kısa gecikmeli aygıtlarda veya düşük seviyeli kimi yüksek performanslı veri yollarında kesilme maliyetinden kaçınmak için bilinçli olarak kullanılabilir.

Temel karar şudur:

Bekleme maliyeti mi, kesilme ve bağlam değiştirme maliyeti mi daha yüksektir?

Kesilme düzeneği

Aygıtın işlemciye hizmet gereksinimini bildirmesine kesilme, yani interrupt denir.

Kesilme sayesinde işlemci aygıtı sürekli kontrol etmek zorunda değildir.

Genel akış şöyledir:

  1. işlemci aygıtta işlemi başlatır,
  2. başka kod çalıştırmaya devam eder,
  3. aygıt işlemi tamamlar,
  4. kesilme üretir,
  5. işlemci mevcut bağlamı korur,
  6. kesilme hizmet yordamına geçer,
  7. gerekli işlemi yapar,
  8. önceki programa döner.

Bu yöntem özellikle gecikmesi işlemci zamanına göre uzun olan aygıtlarda etkilidir.

Kesilme maskesi

Her kesilme aynı önemde değildir.

Bazı kesilmeler geçici olarak engellenebilir. Bu işleme masking denir.

Maske mekanizması kritik kod parçalarının belirli kesilmeler tarafından bölünmesini engellemek veya kesilmeler arasında öncelik kurmak için kullanılabilir.

Buna karşılık belirli donanımsal hata sınıfları gibi bazı olaylar maskelenemeyen kesilmeler şeklinde tasarlanabilir.

Kesilmelerin uzun süre kapalı tutulması kötü bir tasarımdır. Kesilme gecikmesini artırır ve gerçek zamanlı davranışı bozar.

Kesilme vektörü

İşlemcinin hangi kesilme için hangi hizmet yordamına gideceğini bilmesi gerekir.

Bu amaçla kesilme vektörü veya benzeri bir yönlendirme yapısı kullanılır.

Kesilme kaynağı tanındıktan sonra ilgili ISR, yani Interrupt Service Routine, çalıştırılır.

Modern sistemlerde kesilme denetleyicileri çok sayıda aygıt ve işlemci çekirdeği arasındaki kesilmelerin yönlendirilmesini ve önceliklendirilmesini yönetir.

Kesilme hizmet yordamı

Kesilme hizmet yordamı mümkün olduğunca kısa tutulmalıdır.

Tipik görevleri şunlardır:

  • kesilmenin nedenini belirlemek,
  • aygıt durumunu okumak,
  • gerekli en kısa donanım işlemini yapmak,
  • kesilmeyi doğrulamak,
  • daha uzun işi sonraki bir yürütme bağlamına bırakmak.

Uzun süren işlemlerin doğrudan kesilme bağlamında yapılması diğer kesilmelerin gecikmesine neden olabilir.

Kesilmeli G/Ç

Kesilmeli G/Ç, polling yaklaşımındaki sürekli durum kontrolünü ortadan kaldırır.

Bir süreç G/Ç başlattığında bekler durumuna geçirilebilir. İşlemci başka bir sürece verilir.

Aygıt kesilme ürettiğinde işletim sistemi ilgili süreci yeniden hazır duruma getirir.

Bu ilişki işletim sistemi mimarisinin önemli bir bağlantısını gösterir:

G/Ç isteği
    ↓
süreç bekler
    ↓
işlemci başka sürece geçer
    ↓
G/Ç tamamlanır
    ↓
kesilme
    ↓
süreç hazır olur

G/Ç yönetimi ile süreç yönetimi bu nedenle doğrudan bağlantılıdır.

Doğrudan bellek erişimi

Büyük veri bloklarının her baytını işlemci üzerinden taşımak pahalıdır.

DMA - Direct Memory Access, aygıt ile ana bellek arasında veri aktarımının işlemcinin her veri sözcüğünü tek tek taşımasına gerek kalmadan yapılmasını sağlar.

İşlemci genel olarak:

  1. aktarım adresini,
  2. aktarım yönünü,
  3. veri miktarını

belirler ve DMA işlemini başlatır.

Aktarım donanım tarafından gerçekleştirilir. Tamamlandığında işlemciye kesilme gönderilebilir.

Modern sistemlerde DMA adres alanı ile işlemcinin fiziksel adres alanı aynı olmak zorunda değildir. IOMMU gibi birimler aygıt erişimlerini eşleyebilir ve sınırlandırabilir. Güncel Linux DMA API'si de sürücünün CPU sanal adresi, fiziksel adres ve aygıtın görebildiği DMA adresi arasındaki farkı dikkate almasını gerektirir. (cdn.kernel.org)

G/Ç kanalları ve yardımcı işlemciler

Klasik büyük sistemlerde G/Ç kanalları, G/Ç işlemlerinin önemli bölümünü ana işlemciden bağımsız yürütmek için kullanılmıştır.

Temel düşünce bugün de geçerlidir.

Modern depolama ve ağ denetleyicileri:

  • komut kuyrukları,
  • DMA,
  • donanımsal sıra yönetimi,
  • çoklu kesilme vektörleri,
  • paralel işlem kuyrukları

kullanarak işlemci üzerindeki G/Ç yükünü azaltabilir.

Buradaki genel ilke şudur:

İşlemci veri taşıyan birim olmaktan çıkarılır, işlemi başlatan ve denetleyen birim haline getirilir.

Ünite 3: Görev Yönetimi

Görevin tanımı

Çalışan program süreç, ders terminolojisindeki adıyla görev olarak ele alınır.

Program pasif bir kod ve veri bütünüdür. Süreç ise çalışma durumuna sahiptir.

Bir sürecin durumu yalnız koddan oluşmaz. İşletim sistemi süreç için ayrıca:

  • işlemci bağlamı,
  • adres alanı,
  • açık dosyalar,
  • kaynak sahipliği,
  • kullanıcı kimliği,
  • sinyal durumu,
  • planlama bilgileri

tutar.

Görev anahtarlama

İşlemci bir süreçten başka bir sürece geçirildiğinde context switch, yani bağlam anahtarlama yapılır.

Eski sürecin gerekli işlemci durumu saklanır. Yeni sürecin daha önce saklanmış durumu işlemciye yüklenir.

Bağlam tipik olarak şunları kapsar:

  • program sayacı,
  • yığıt göstergesi,
  • genel amaçlı yazmaçlar,
  • işlemci durum bilgileri,
  • gerektiğinde adres alanıyla ilişkili bilgiler.

Bağlam değiştirme gerekli olsa da doğrudan kullanıcı işi üretmez. Bu nedenle işletim sistemi açısından bir yönetim maliyetidir.

Zaman dilimlerinin aşırı küçük seçilmesi çok sayıda bağlam anahtarlamasına neden olur.

Süreç durumları

Basit bir süreç modeli üç temel durumla açıklanabilir:

Ready: Süreç çalışmaya hazırdır ancak işlemciyi bekler.

Running: Süreç işlemci üzerinde çalışmaktadır.

Blocked/Waiting: Süreç G/Ç, kilit, zamanlayıcı veya başka bir olay beklemektedir.

Tipik geçişler şöyledir:

        dispatch
READY -----------> RUNNING
  ^                   |
  |                   |
  | preemption        | wait
  |                   v
  +--------------- WAITING
          event

Süreç oluşturma ve sonlandırma durumları eklendiğinde model genişler.

Görev kuyrukları

İşletim sistemi süreçleri durumlarına göre kuyruklarda tutabilir.

En temel kuyruk hazır kuyruğudur.

Bunun yanında:

  • disk bekleme kuyruğu,
  • ağ bekleme kuyruğu,
  • kilit bekleme kuyruğu,
  • zamanlayıcı bekleme yapıları

bulunabilir.

Bir olay tamamlandığında süreç ilgili bekleme yapısından çıkarılır ve yeniden hazır duruma alınır.

Süreç oluşturma

Unix süreç modelinin temel işlemlerinden biri fork() çağrısıdır.

fork() çalışan sürecin yeni bir çocuk süreç oluşturmasını sağlar.

Yeni program görüntüsüne geçiş ise exec() ailesiyle yapılabilir.

Klasik kalıp şöyledir:

fork()
    ├─ ebeveyn süreç
    └─ çocuk süreç
           ↓
         exec()
           ↓
       yeni program

Bu ayrım önemlidir:

fork() yeni süreç yaratır.

exec() mevcut sürecin çalıştırdığı programı değiştirir.

POSIX ailesinde süreç ve komut çalıştırma arayüzleri bu model etrafında tanımlanır. (pubs.opengroup.org)

Süreç sonlandırma ve bekleme

Bir süreç tamamlandığında çıkış durumunu işletim sistemine bildirir.

Ebeveyn süreç çocuk sürecin sonucunu alabilir.

Unix modelinde çocuk süreç sonlanmış ancak ebeveyni henüz durumunu almamışsa süreç kaydı kısa süreyle zombie durumunda kalabilir.

Bu bir "çalışmaya devam eden ölü süreç" değildir. Program çalışması bitmiştir. Yalnızca ebeveynin alacağı sonlanma bilgisi süreç tablosunda tutulmaktadır.

İşlemci planlama

Hazır durumda birden fazla süreç bulunduğunda hangi sürecin işlemciyi alacağına scheduler karar verir.

Planlama algoritmaları değerlendirilirken şu ölçütler kullanılır:

  • CPU kullanımı,
  • throughput,
  • turnaround time,
  • waiting time,
  • response time,
  • adalet,
  • öncelik,
  • gerçek zamanlı sistemlerde deadline uyumu.

Tek bir algoritma bütün ölçütleri aynı anda en iyi yapamaz.

İlk gelen önce

FCFS - First Come First Served, hazır kuyruğuna önce gelen süreci önce çalıştırır.

Basittir ve aç kalma sorunu düşüktür.

Ancak uzun bir CPU ağırlıklı süreç kuyruğun başına geçtiğinde kısa süreçler uzun süre bekleyebilir. Bu durum convoy effect olarak bilinir.

En kısa iş önce ve SRTF

Shortest Job First, işlem süresi en kısa olan işi seçer.

Kuramsal olarak ortalama bekleme süresini düşürebilir. Ancak gelecekteki CPU süresini kesin olarak bilmek çoğu durumda mümkün değildir.

Shortest Remaining Time First, bu yaklaşımın preemptive biçimidir. Kalan çalışma süresi daha kısa bir süreç geldiğinde çalışan süreç kesilebilir.

Öncelik tabanlı planlama

Her sürece bir öncelik değeri verilir.

Planlayıcı daha yüksek öncelikli süreci önce çalıştırır.

Bu yöntem gerçek zamanlı ve sistem görevlerinde önemlidir.

Ancak sürekli yüksek öncelikli işler gelirse düşük öncelikli görevler uzun süre işlemci alamayabilir. Buna starvation denir.

Bir çözüm, bekledikçe süreç önceliğini yükselten aging yaklaşımıdır.

Round Robin

Round Robin, etkileşimli sistemlerin temel planlama yaklaşımlarındandır.

Her sürece belirli bir time quantum verilir.

Süreç zaman dilimi içinde bitmez veya bloke olmazsa kesilir ve hazır kuyruğunun sonuna alınır.

Quantum çok büyükse davranış FCFS'ye yaklaşır.

Quantum çok küçükse bağlam değiştirme maliyeti yükselir.

Bu nedenle zaman dilimi seçimi gecikme ile yönetim maliyeti arasında dengedir.

Çok düzeyli kuyruklar

Farklı iş türleri farklı kuyruklarda tutulabilir.

Örneğin:

  • gerçek zamanlı görevler,
  • etkileşimli görevler,
  • toplu işler

farklı planlama politikalarına sahip olabilir.

Multilevel Feedback Queue yaklaşımında süreçler davranışlarına göre kuyruklar arasında hareket edebilir.

Kısa CPU patlamaları kullanan etkileşimli süreçlere daha hızlı yanıt verilirken uzun CPU ağırlıklı süreçler daha düşük öncelikli kuyruklara taşınabilir.

Uzun, orta ve kısa dönemli planlama

Klasik işletim sistemi modeli üç planlama düzeyi tanımlar.

Uzun dönemli planlama, hangi işlerin sisteme kabul edileceğini belirler.

Orta dönemli planlama, süreçlerin bellek ile ikincil depolama arasındaki durumunu yönetebilir.

Kısa dönemli planlama, hazır süreçlerden hangisinin işlemciye verileceğine karar verir.

Modern genel amaçlı işletim sistemlerinde bu ayrımlar klasik toplu işlem sistemlerindeki kadar görünür olmayabilir. Ancak kaynak kabulü, bellek baskısı ve CPU planlama arasında farklı zaman ölçeklerinin bulunması halen geçerli bir tasarım düşüncesidir.

Thread kavramı

Bir süreç içinde birden fazla komut akışı bulunabilir. Bunlara thread, eski Türkçe kullanımda işletim dizisi denir.

Aynı sürecin thread'leri genellikle:

  • kod alanını,
  • veri alanını,
  • heap'i,
  • açık dosyaları

paylaşır.

Her thread'in ise kendi:

  • program sayacı,
  • yazmaç bağlamı,
  • yığıtı

bulunur.

Thread oluşturmak ve aralarında geçiş yapmak çoğu durumda ayrı süreçlerden daha düşük maliyetlidir. Bunun karşılığında paylaşılan bellek nedeniyle eşzamanlama hataları daha kolay ortaya çıkar.

Ünite 4: Birlikte Çalışan Görevler

Koşut çalışma ve kaynak paylaşımı

Birden fazla süreç veya thread aynı veri üzerinde çalıştığında yalnız işlem sırası değil, işlemlerin birbirleriyle etkileşimi de önem kazanır.

Paylaşılan kaynak:

  • değişken,
  • bellek bölgesi,
  • dosya,
  • veri yapısı,
  • aygıt,
  • kuyruk

olabilir.

İki çalışma akışının aynı kaynağa kontrolsüz erişmesi race condition oluşturabilir.

Race condition

Şu işlemi ele alalım:

sayac = sayac + 1

Bu ifade işlemci açısından tek bir işlem olmak zorunda değildir.

Kabaca:

R1 = sayac
R1 = R1 + 1
sayac = R1

şeklinde yürütülebilir.

İki thread aynı anda çalışırsa ikisi de eski değeri okuyabilir. Sonuçta iki artış yapılmasına rağmen sayaç yalnız bir artmış olabilir.

Programın sonucu yürütme sırasına bağlı hale gelmiştir.

Kritik kesim

Paylaşılan kaynağa erişen kod bölümüne kritik kesim denir.

Doğru bir karşılıklı dışlama çözümü temel olarak şunları sağlamalıdır:

  1. aynı anda yalnız bir yürütme akışı kritik kesimde bulunmalıdır,
  2. kritik kesim boşsa uygun bir görev gereksiz yere engellenmemelidir,
  3. bir görev sonsuza kadar bekletilmemelidir,
  4. çözüm işlem hızlarına ilişkin hatalı varsayımlara dayanmamalıdır.

Kesilmeleri kapatma

Tek işlemcili basit sistemlerde kritik bir işlem sırasında kesilmelerin geçici olarak kapatılması karşılıklı dışlama sağlayabilir.

Ancak bu yaklaşım kullanıcı programlarına bırakılamaz.

Ayrıca çok çekirdekli sistemde bir çekirdekte kesilmeyi kapatmak diğer çekirdeğin aynı belleğe erişmesini engellemez.

Bu nedenle yöntem yalnız sınırlı çekirdek içi kritik bölgelerde anlamlıdır.

Yazılımsal karşılıklı dışlama

Dekker ve Peterson algoritmaları karşılıklı dışlamanın yalnız paylaşılan değişkenlerle kurulabileceğini gösteren klasik çözümlerdir.

Bu algoritmalar işletim sistemi düşüncesi açısından önemlidir. Ancak modern genel amaçlı eşzamanlama mekanizmalarının doğrudan temeli olarak kullanılmazlar.

Asıl ders şudur:

Paylaşılan değişkenlere sıradan okuma ve yazma işlemleri yapmak güvenli eşzamanlama için her zaman yeterli değildir.

Atomik işlemler

Modern işlemciler karşılıklı dışlamayı kurmak için atomik makine işlemleri sağlar.

Örnek kavramlar:

  • test-and-set,
  • compare-and-swap,
  • atomic exchange,
  • fetch-and-add.

Atomik işlem, diğer işlemcilerin araya giremeyeceği şekilde tek bir mantıksal işlem olarak görülür.

Bunlar mutex, spinlock ve daha gelişmiş eşzamanlama yapılarının temelini oluşturabilir.

Spinlock

Bir thread kilit serbest kalana kadar döngü içinde bekliyorsa spinlock kullanımı söz konusudur.

Spinlock kısa kritik bölgelerde yararlı olabilir.

Bekleme uzun olacaksa işlemciyi sürekli tüketmek verimsizdir. Bu durumda thread'in uyutulması daha uygundur.

Temel seçim:

  • çok kısa bekleme: spin,
  • uzun veya belirsiz bekleme: block/sleep.

Semafor

Semafor, Dijkstra tarafından ortaya konan temel eşzamanlama soyutlamalarındandır.

Klasik işlemleri:

  • P() veya wait(),
  • V() veya signal()

olarak gösterilir.

İkili semaforun değeri 0 veya 1 olabilir ve karşılıklı dışlama amacıyla kullanılabilir.

Saymalı semafor ise aynı türden birden fazla kaynağın sayısını temsil edebilir.

Örneğin havuzda dört eş kaynak varsa semafor başlangıç değeri 4 olabilir.

Bir görev kaynak aldığında değer azalır. Kaynak geri verildiğinde artar.

Mutex ve semafor ayrımı

Mutex özellikle bir kritik bölgenin sahipliğini denetlemek için tasarlanır.

Semafor ise kaynak sayımı veya olay bildirimi için de kullanılabilir.

Bu iki mekanizma kimi durumlarda birbirinin yerine kullanılabilse de semantik olarak aynı değildir.

Mutex'in sahiplik kavramı vardır. Kilidi alan thread'in bırakması beklenir.

Monitör

Monitor, paylaşılan veri ile bu veri üzerinde çalışan işlemleri tek bir kontrollü yapı içinde birleştiren üst düzey eşzamanlama yaklaşımıdır.

Aynı anda yalnız bir thread monitör içinde aktif olabilir.

Koşul değişkenleri belirli koşullar gerçekleşene kadar thread'lerin beklemesini sağlar.

Bu yaklaşım düşük seviyeli semafor kullanımına göre programlama hatalarını azaltabilir.

İleti aktarımı

Görevlerin aynı belleği paylaşması zorunlu değildir.

Bir süreç diğerine ileti göndererek de eşgüdüm sağlayabilir.

Temel işlemler:

send(destination, message)
receive(source, message)

İleti aktarımı:

  • aynı sistemde süreçler arasında,
  • farklı makinelerde ağ üzerinden

kullanılabilir.

Bu nedenle ileti aktarımı hem eşzamanlama hem de dağıtık sistem tasarımının temel araçlarındandır.

Kilitlenme

Bir grup süreç birbirinin elindeki kaynakları beklediği için hiçbirinin ilerleyemediği duruma deadlock, yani kilitlenme denir.

Klasik örnek:

G1:
    disk kilidini al
    yazıcı kilidini bekle

G2:
    yazıcı kilidini al
    disk kilidini bekle

Her iki görev de diğerinin kaynağı bırakmasını bekler.

Kilitlenmenin gerekli koşulları

Klasik deadlock modelinde dört koşul birlikte bulunmalıdır:

  1. Mutual exclusion: Kaynak aynı anda yalnız bir görev tarafından kullanılabilir.
  2. Hold and wait: Görev elindeki kaynağı bırakmadan başka kaynak bekler.
  3. No preemption: Kaynak görevden zorla alınamaz.
  4. Circular wait: Görevler arasında döngüsel bekleme oluşur.

Bu koşullardan en az biri sistematik olarak ortadan kaldırılırsa deadlock önlenebilir.

Kaynakları sıralama

Deadlock önlemenin pratik yollarından biri kaynaklara global sıra vermektir.

Örneğin:

R1 < R2 < R3 < R4

Tüm görevler kaynakları yalnız artan sırada alırsa dairesel bekleme oluşmaz.

Bu yöntem özellikle birden fazla kilidin birlikte kullanıldığı yazılımlarda etkilidir.

Banker algoritması

Banker algoritması deadlock'tan kaçınmaya yönelik klasik bir yöntemdir.

Kaynak isteği ancak sistem yeni atamadan sonra güvenli durumda kalıyorsa karşılanır.

Güvenli durum, tüm görevlerin uygun bir sırayla tamamlanabileceği en az bir kaynak tahsis dizisinin bulunmasıdır.

Algoritmanın önemli sınırlaması görevlerin maksimum kaynak gereksinimlerinin önceden bilinmesini gerektirmesidir.

Bu nedenle genel amaçlı işletim sistemlerinde her kaynak için doğrudan uygulanması pratik değildir. Ancak güvenli kaynak tahsisi düşüncesini anlamak açısından önemlidir.

Ünite 5: Ana Bellek Yönetimi

Bellek yönetiminin amacı

Programın çalışabilmesi için komutlarının ve gerekli verilerinin işlemcinin erişebildiği bellekte bulunması gerekir.

Birden fazla süreç aynı anda çalıştığında işletim sistemi belleği süreçler arasında paylaştırır.

Bellek yönetimi şu sorunları çözmelidir:

  • hangi alanın boş olduğunu bilmek,
  • süreçlere yer ayırmak,
  • serbest kalan alanları geri almak,
  • süreçleri birbirinden korumak,
  • mantıksal adresleri fiziksel adreslere dönüştürmek,
  • fiziksel bellekten daha büyük adres alanları sunabilmek.

Mantıksal ve fiziksel adres

Programın gördüğü adres ile gerçek RAM konumu aynı olmak zorunda değildir.

Sanal veya mantıksal adres, programın kullandığı adrestir.

Fiziksel adres, bellekteki gerçek konumdur.

Adres dönüşümü işlemcinin bellek yönetim birimi, yani MMU, tarafından işletim sisteminin oluşturduğu veri yapıları yardımıyla yapılır.

Bu ayrım modern bellek yönetiminin temelidir.

Değişmez bölümlü bellek

En basit çok programlı bellek yönetimlerinden biri belleği önceden belirlenen bölümlere ayırmaktır.

Her bölüm bir sürece verilir.

Yöntem basittir ancak ciddi bir sorun üretir.

Bir süreç kendisine ayrılan bölümden küçükse kullanılmayan alan boşa gider.

Bu kayıp internal fragmentation olarak adlandırılır.

Değişken bölümlü bellek

Bellek sabit boyutlu bölümlere ayrılmak yerine süreç gereksinimine göre bölünebilir.

Bu yaklaşım iç parçalanmayı azaltır.

Ancak zaman içinde küçük boşluklar oluşur.

Toplam boş alan yeterli olmasına rağmen tek parça halinde büyük bir süreç için kullanılamayabilir.

Bu durum external fragmentation olarak bilinir.

Boş alan seçme algoritmaları

Değişken bölümlü yönetimde boş alan seçmek için klasik algoritmalar kullanılabilir.

First fit: İlk yeterli boşluğu seçer.

Best fit: İsteği karşılayan en küçük boşluğu seçer.

Worst fit: En büyük boşluğu seçer.

Hiçbiri bütün iş yüklerinde mutlak üstün değildir.

Bellek tahsis algoritmalarının davranışı iş yükündeki nesne boyutlarına ve tahsis ömürlerine bağlıdır.

Bitiştirme

Dış parçalanmayı azaltmak için kullanılan klasik yöntemlerden biri compaction işlemidir.

Kullanılan bellek bölgeleri taşınarak boş alanlar bir araya getirilir.

Bu işlem maliyetlidir. Bellekteki büyük miktarda verinin taşınmasını ve adreslerin yeniden düzenlenmesini gerektirebilir.

Sayfalama gibi modern yöntemlerin önemli avantajlarından biri fiziksel bellekte böyle bir bitişik alan zorunluluğunu büyük ölçüde ortadan kaldırmasıdır.

Yeniden yerleştirme

Program bellekte her zaman aynı fiziksel adreste çalıştırılmak zorunda olmamalıdır.

Bu gereksinim relocation kavramını doğurur.

Mantıksal adres ile fiziksel adres arasındaki dönüşüm donanım desteğiyle yapılırsa süreç belleğin farklı bir fiziksel bölümüne yerleştirilebilir.

Sanal bellek bu düşüncenin çok daha gelişmiş biçimidir.

Swapping

Bellek baskısı oluştuğunda bir sürecin bazı veya tüm bellek içeriğinin ikincil depolamaya taşınması swapping olarak adlandırılır.

Klasik sistemlerde tüm süreç görüntüsü taşınabilirdi.

Modern sanal bellek sistemlerinde çoğunlukla süreç bütünü yerine belirli bellek sayfalarının geri kazanılması söz konusudur.

Kalıcı depolama RAM'den çok daha yavaş olduğundan yoğun swapping ciddi performans düşüşüne neden olabilir.

Sayfalama

Sayfalama fiziksel belleği sabit boyutlu frame'lere, sanal adres alanını aynı boyutlu page'lere böler.

Bir sanal adres iki parçadan oluşur:

sanal adres = sayfa numarası + sayfa içi ofset

Sayfa numarası sayfa tablosunda aranır.

Elde edilen fiziksel frame numarası ofsetle birleştirilir.

virtual page
     ↓
page table
     ↓
physical frame
     +
offset
     ↓
physical address

Sayfalama fiziksel bellekte bitişik yer zorunluluğunu ortadan kaldırır.

Sayfa tablosu

Her süreç sanal sayfaların fiziksel frame'lerle ilişkisini gösteren sayfa tablosuna sahiptir.

Bir sayfa tablosu girdisi yalnız frame numarasını içermez.

Genellikle şu tür durum bilgileri de bulunabilir:

  • sayfa geçerli mi,
  • okunabilir mi,
  • yazılabilir mi,
  • kullanıcı modundan erişilebilir mi,
  • değiştirilmiş mi,
  • yakın zamanda erişilmiş mi.

Bu bitler hem sanal bellek hem de koruma için kullanılır.

TLB

Her bellek erişiminde sayfa tablosunu RAM'den okumak pahalıdır.

Bu nedenle işlemciler son adres dönüşümlerini TLB - Translation Lookaside Buffer içinde saklar.

TLB isabetinde sayfa tablosuna gitmeye gerek kalmaz.

TLB kaçırıldığında gerekli adres dönüşümü sayfa tablolarından elde edilir.

Bellek erişim performansında TLB davranışı bu nedenle kritik önemdedir.

Çok düzeyli sayfa tabloları

Geniş sanal adres alanlarında tek düzeyli sayfa tablosu çok büyük olabilir.

Çok düzeyli sayfa tabloları adres alanını hiyerarşik olarak böler.

Yalnız kullanılan bölümler için alt düzey tablo oluşturulabilir.

Modern 64 bit mimarilerde çok düzeyli adres dönüşümü yaygındır.

Bellek koruması

Sayfalama yalnız adres çevrimi sağlamaz.

Her sayfaya erişim izinleri atanabilir.

Örneğin:

R   okuma
W   yazma
X   çalıştırma

Kod sayfaları salt okunur ve çalıştırılabilir tutulabilir.

Veri sayfalarının çalıştırılması engellenebilir.

Kullanıcı süreçlerinin çekirdek sayfalarına erişmesi donanım seviyesinde sınırlandırılabilir.

Kesimleme

Segmentation, adres alanını programın mantıksal yapılarına göre değişken uzunluklu kesimlere ayırır.

Örneğin:

  • kod,
  • veri,
  • yığıt

ayrı kesimler olabilir.

Bir mantıksal adres:

segment + offset

biçiminde düşünülür.

Her segment için taban, sınır ve koruma bilgileri tutulabilir.

Sayfalama fiziksel bellek yönetimi açısından daha düzenli olduğu için modern genel amaçlı sistemlerde baskın mekanizmadır. Buna rağmen mantıksal bölge kavramı sanal adres alanlarında yaşamaya devam eder.

Sanal bellek

Sanal bellek, bir sürece fiziksel RAM'de aynı anda bulunandan daha büyük ve bağımsız bir adres alanı sunar.

Programın bütün sayfalarının RAM'de bulunması gerekmez.

Yalnız kullanılan sayfalar belleğe getirilebilir.

Bu yaklaşım demand paging olarak bilinir.

Linux'un güncel bellek yönetimi de süreç adres alanları, sayfa tabloları, page reclaim, swap ve page cache gibi mekanizmaları ayrı alt sistemler olarak yönetmektedir. (kernel.org)

Sayfa hatası

Program RAM'de bulunmayan ancak geçerli bir sanal sayfaya erişirse page fault oluşur.

İşletim sistemi:

  1. erişimin geçerli olup olmadığını denetler,
  2. uygun bir fiziksel frame bulur,
  3. gerekiyorsa başka bir sayfayı çıkarır,
  4. istenen sayfayı depolamadan yükler,
  5. sayfa tablosunu günceller,
  6. işlemi yeniden başlatır.

Disk veya SSD erişimi gerektiğinde page fault maliyeti sıradan RAM erişiminden çok büyüktür.

Sayfa çıkarma algoritmaları

Boş frame kalmadığında hangi sayfanın çıkarılacağına karar verilmelidir.

FIFO

Belleğe en önce giren sayfa çıkarılır.

Uygulaması kolaydır ancak erişim davranışını dikkate almaz.

FIFO bazı durumlarda frame sayısı arttığında bile daha fazla page fault üretebilir. Bu olay Belady anomalisi olarak bilinir.

LRU

Least Recently Used, en uzun süredir erişilmeyen sayfayı çıkarmaya çalışır.

Programların zaman yerelliğinden yararlanır.

Tam LRU bilgisinin tutulması pahalı olabilir. Bu nedenle gerçek sistemler yaklaşık LRU davranışı sağlayan yöntemler kullanabilir.

Optimal

Gelecekte en uzun süre kullanılmayacak sayfa çıkarılır.

Bu yöntem en düşük mümkün page fault sayısını verir ancak gelecekteki erişimleri bilmek gerektiğinden gerçek sistemde uygulanamaz.

Karşılaştırma ölçütü olarak önemlidir.

Yerellik

Sanal belleğin çalışabilmesinin temel nedeni programların locality of reference özelliğidir.

Temporal locality: Yakın zamanda kullanılan veri tekrar kullanılma eğilimindedir.

Spatial locality: Bir adrese erişildiğinde yakın adreslere de erişilme olasılığı yüksektir.

Program aktif çalışma kümesini bellekte tutabiliyorsa iyi performans gösterir.

Aktif sayfalar RAM'e sığmıyorsa sürekli sayfa değiştirme oluşabilir. Buna thrashing denir.

Kesimli ve sayfalı sanal bellek

Kesimleme ile sayfalama birlikte kullanılabilir.

Mantıksal adres önce segmenti belirler. Segment içindeki sanal adres daha sonra sayfa tabloları üzerinden fiziksel frame'e çevrilir.

Bu yaklaşım kavramsal olarak:

mantıksal adres
     ↓
segment
     ↓
sanal sayfa
     ↓
page table
     ↓
physical frame

şeklinde düşünülebilir.

Modern işlemcilerde ayrıntılar mimariye bağlıdır. Kalıcı fikir, programın gördüğü adres alanının fiziksel RAM düzeninden soyutlanmasıdır.

Ünite 6: Kütük ve Dosya Yönetimi

Dosya kavramı

Ders terminolojisindeki kütük, güncel kullanımda dosya olarak adlandırılır.

Dosya, kalıcı depolamada tutulan adlandırılmış veri bütünüdür.

İşletim sistemi fiziksel depolama ayrıntılarını kullanıcıdan gizler.

Program:

dosyayı aç
veriyi oku
veriyi yaz
konumu değiştir
dosyayı kapat

gibi mantıksal işlemler kullanır.

Dosyanın fiziksel olarak hangi bloklarda saklandığını bilmek zorunda değildir.

Dosya öznitelikleri

Dosya sistemi dosyanın içeriği dışında metadata da tutar.

Tipik bilgiler:

  • ad,
  • tür,
  • boyut,
  • sahip,
  • grup,
  • izinler,
  • zaman bilgileri,
  • fiziksel yer bilgileri,
  • bağlantı sayısı.

Dosyanın adı ile fiziksel verisinin aynı yapı olması gerekmez. Ad genellikle dizin yapısındaki bir kayıt üzerinden dosyanın metadata nesnesine bağlanır.

Dizin yapısı

Dosyaların tek düzeyde tutulması büyük sistemler için yetersizdir.

Bu nedenle hiyerarşik dizin yapısı kullanılır.

Örnek:

/
├── home
│   └── user
│       ├── documents
│       └── projects
└── var
    └── log

Bir dosya absolute path veya relative path ile belirtilebilir.

Hiyerarşi ad çakışmalarını azaltır ve verilerin mantıksal olarak gruplandırılmasını sağlar.

Temel dosya işlemleri

Dosya sistemi tipik olarak şu işlemleri sağlar:

  • create,
  • open,
  • close,
  • read,
  • write,
  • seek,
  • truncate,
  • rename,
  • delete,
  • stat.

Unix benzeri sistemlerde açık dosya çoğunlukla bir file descriptor ile temsil edilir.

open() bir descriptor döndürür. Sonraki read() ve write() çağrıları bu descriptor üzerinden yapılır.

Bu yapı uygulamanın fiziksel dosya sistemi ayrıntılarından bağımsız çalışmasını sağlar.

Fiziksel depolama

Klasik dosya sistemi anlatımı dönen manyetik diskleri temel alır.

Bu disklerde erişim süresi:

  • kafa hareketi,
  • döndürme gecikmesi,
  • veri aktarımı

gibi bileşenlerden etkilenir.

SSD'lerde mekanik kafa ve döndürme gecikmesi yoktur. Bunun yerine flash sayfaları, erase block'lar, denetleyici, wear leveling ve flash translation layer gibi farklı özellikler vardır.

Bu nedenle modern dosya sistemi optimizasyonunda yalnız klasik disk geometrisine göre düşünmek doğru değildir.

Buna rağmen işletim sistemi depolamayı mantıksal bloklar üzerinden yönetmeye devam eder.

Dosya sistemi katmanları

Dosya erişimi birkaç soyutlama düzeyinden geçebilir:

uygulama
   ↓
sistem çağrısı
   ↓
VFS
   ↓
dosya sistemi
   ↓
önbellek
   ↓
blok G/Ç
   ↓
aygıt sürücüsü
   ↓
depolama aygıtı

Linux'taki Virtual File System farklı dosya sistemi gerçekleştirimlerinin ortak open, read, write, stat gibi arayüzlerle kullanılmasını sağlayan çekirdek soyutlama katmanıdır. (docs.kernel.org)

FAT yaklaşımı

FAT ailesinde depolama bloklarının bağlantıları merkezi bir File Allocation Table içinde tutulur.

Bir dosyanın ilk kümesi bilindiğinde zincir tablo üzerinden izlenebilir.

Yöntem basit ve taşınabilirdir.

Ancak çok büyük dosya sistemlerinde merkezi tablo ve zincir yapısı ölçeklenebilirlik açısından sınırlıdır.

FAT bugün de çeşitli çıkarılabilir depolama ortamlarında kullanılmasına rağmen modern genel amaçlı dosya sistemlerinin tek modeli değildir.

inode

Unix ailesinin önemli kavramlarından biri inode yapısıdır.

inode dosyanın:

  • türünü,
  • izinlerini,
  • sahibini,
  • boyutunu,
  • zaman bilgilerini,
  • veri bloklarına erişim bilgilerini

tutar.

Dosya adı doğrudan inode'un kendisinde tutulmak zorunda değildir. Dizin kaydı adı inode benzeri metadata nesnesine eşler.

Bu ayrım hard link kavramının da temelidir.

Bağlantılar

Bir dosyanın aynı dosya sistemi içinde birden fazla adı olabilir.

Hard link, aynı dosya nesnesine başka bir dizin girdisi oluşturur.

Symbolic link, başka bir yol adını içeren ayrı bir dosya nesnesidir.

Hard link ve symbolic link aynı mekanizma değildir.

Bitişik yer ayırma

Dosyanın blokları fiziksel olarak ardışık tutulabilir.

Avantajları:

  • basit metadata,
  • yüksek sıralı erişim performansı,
  • hızlı rastgele erişim.

Sorunları:

  • dosyanın gelecekteki boyutunu tahmin etmek güçtür,
  • büyüme zor olabilir,
  • dış parçalanma oluşabilir.

Modern dosya sistemlerinde bunun geliştirilmiş biçimi olan extent yapıları yaygın olarak kullanılır. Tek tek blok yerine ardışık blok aralıkları tanımlanır.

Zincirli yer ayırma

Her blok bir sonraki bloğun adresini taşır.

Dosyanın büyümesi kolaydır.

Ancak rastgele erişim verimsizdir. Bir bloğa ulaşmak için önceki bağlantıların izlenmesi gerekebilir.

Bağlantı bilgisi bozulduğunda zincirin geri kalanı kaybedilebilir.

FAT yaklaşımı bağlantı bilgisini blokların içinden alıp merkezi tabloya taşıyarak bu modelin bir çeşidini uygular.

Dizinli yer ayırma

Dosyanın veri bloklarının adresleri bir dizin yapısında tutulabilir.

Bu yöntem rastgele erişimi kolaylaştırır.

Unix inode yapısındaki doğrudan ve dolaylı blok göstergeleri bunun klasik örneklerindendir.

Modern dosya sistemleri büyük dosyalar için ağaç yapıları ve extent tabanlı metadata kullanabilir.

Dosya önbelleği

Depolama erişimi RAM erişiminden çok daha yavaştır.

Bu nedenle sık kullanılan dosya verileri ana bellekte önbelleğe alınır.

Okuma sırasında veri önbellekte bulunursa fiziksel aygıta erişmek gerekmez.

Yazma işlemleri de bazı sistemlerde önce bellekte tutulup daha sonra depolamaya aktarılabilir.

Bu yaklaşım performansı artırır ancak güç kesintisi ve sistem çökmesi sırasında tutarlılık sorunları yaratabilir.

Yazma stratejileri

Write-through yaklaşımında değişiklik kısa sürede kalıcı depolamaya aktarılır.

Write-back yaklaşımında değişiklik önce bellekte tutulur ve daha sonra yazılır.

Write-back daha yüksek performans sağlayabilir ancak henüz kalıcı hale gelmemiş verinin kaybedilme riski vardır.

Bu nedenle dosya sistemi güvenilirliği yalnız veri bloklarının değil metadata güncellemelerinin de doğru sıralanmasını gerektirir.

Dosya sistemi tutarlılığı

Bir dosya oluşturulurken birden fazla metadata yapısı değişebilir.

Sistem bu işlemlerin ortasında çökerse dosya sistemi kısmen güncellenmiş durumda kalabilir.

Modern dosya sistemleri bu sorunu azaltmak için:

  • journaling,
  • copy-on-write,
  • checksum,
  • atomic metadata update

gibi tekniklerden yararlanabilir.

Her teknik aynı garanti seviyesini vermez.

RAID

RAID birden fazla fiziksel depolama aygıtını performans veya hata toleransı amacıyla birlikte kullanma yaklaşımıdır.

Örnek düzeyler:

RAID 0: Striping. Performans ve kapasite sağlar, yedeklilik sağlamaz.

RAID 1: Mirroring. Veri iki veya daha fazla kopya halinde tutulur.

RAID 5: Dağıtılmış parity ile tek disk arızasına tolerans sağlar.

RAID 6: İki bağımsız parity bilgisiyle iki disk arızasına tolerans sağlayabilir.

RAID veri erişilebilirliğini artırabilir ancak yedekleme değildir.

Yanlışlıkla silinen, şifrelenen veya bozuk yazılan veri RAID kopyalarına da yayılabilir.

Ünite 7: Güvenlik ve Koruma

Güvenlik ve koruma ayrımı

İşletim sisteminde koruma, sistem kaynaklarının hangi süreç veya kullanıcı tarafından nasıl kullanılabileceğini sınırlar.

Güvenlik daha geniştir. Yetkisiz erişim, veri sızıntısı, kimlik taklidi ve kötü amaçlı yazılım gibi tehditleri de kapsar.

Temel güvenlik hedefleri:

  • gizlilik,
  • bütünlük,
  • kullanılabilirliktir.

Kimlik doğrulama

Sisteme erişmeden önce kullanıcının iddia ettiği kişi olduğunun doğrulanması gerekir.

Kimlik doğrulama faktörleri genel olarak üç gruptur:

  • bildiğiniz şey,
  • sahip olduğunuz şey,
  • olduğunuz şey.

Parola ilk gruba, güvenlik anahtarı veya akıllı kart ikinci gruba, biyometrik özellikler üçüncü gruba girer.

Birden fazla bağımsız faktörün birlikte kullanılması çok faktörlü kimlik doğrulamadır.

Parolalar

Parola doğrulama sisteminin parolayı düz metin biçiminde saklaması doğru değildir.

Parolalar parola saklamaya uygun bir türetme işleviyle ve kullanıcıya özgü salt ile işlenmelidir.

Modern yaklaşım yalnız karmaşık karakter kuralları dayatmak değildir. Yeterli uzunluk, bilinen zayıf veya ele geçirilmiş parolaların engellenmesi ve çevrim içi deneme saldırılarına karşı koruma daha önemlidir. NIST'in güncel dijital kimlik doğrulama kılavuzu da katı karakter bileşimi kuralları yerine uzunluk ve blocklist yaklaşımını öne çıkarmaktadır. (pages.nist.gov)

Parolanın önemli bir sınırlaması phishing'e dirençli olmamasıdır.

Yetkilendirme

Kimlik doğrulama:

Siz kimsiniz?

sorusunu yanıtlar.

Yetkilendirme ise:

Neye erişebilirsiniz?

sorusunu yanıtlar.

Bu iki aşama birbirinden ayrılmalıdır.

Erişim matrisi

Erişim denetiminin temel modellerinden biri erişim matrisidir.

Satırlar kullanıcı, süreç veya koruma alanlarını; sütunlar nesneleri gösterir.

Hücrelerde izinler bulunur.

Örneğin:

| Özne | Dosya A | Dosya B | Aygıt | | --- | --- | --- | --- | | Kullanıcı 1 | R/W | R | - | | Kullanıcı 2 | R | - | X |

Bu matris kuramsal olarak açıktır ancak gerçek sistemlerde tamamını tutmak verimsiz olabilir.

Bu nedenle satır veya sütun yönünde seyrek gösterimler kullanılır.

Erişim denetim listeleri

ACL - Access Control List, nesne merkezli yaklaşımdır.

Her nesne kendisine kimlerin hangi haklarla erişebileceğini tutar.

Örneğin bir dosya:

Ali      read, write
Ayşe     read
GrupA    read

gibi bir erişim listesine sahip olabilir.

Capability yaklaşımı

Capability tabanlı sistemde özne, erişme yetkisine sahip olduğu nesneleri ve hakları temsil eden yeteneklere sahip olur.

Bu yaklaşım erişim matrisinin satır yönünden gerçekleştirimine benzetilebilir.

Modern güvenlik mimarilerinde capability sözcüğü farklı bağlamlarda farklı teknik ayrıntılar taşıyabilir. Temel fikir yetkinin açık ve sınırlandırılmış bir nesne olarak temsil edilmesidir.

Koruma halkaları

İşlemciler farklı ayrıcalık düzeylerini donanımsal olarak destekleyebilir.

Genel amaçlı işletim sistemlerinde en önemli ayrım:

  • kullanıcı modu,
  • çekirdek modu

arasındadır.

Kullanıcı modundaki uygulama kritik işlemci durumunu veya çekirdek belleğini doğrudan değiştiremez.

Sistem çağrısı kontrollü bir ayrıcalık geçişi sağlar.

Bu mekanizma hatalı bir kullanıcı programının tüm sistemi bozmasını engelleyen temel savunmalardan biridir.

En az ayrıcalık ilkesi

Bir bileşene yalnız görevini yerine getirmesi için gerekli yetkiler verilmelidir.

Bu ilkeye least privilege denir.

Bir medya dönüştürücü ağ yapılandırmasını değiştirmek zorunda değilse bu yetkiye sahip olmamalıdır.

Bir sunucu süreci yalnız belirli bir dizine yazacaksa bütün dosya sistemine yazma izni gereksizdir.

Sınırlı yetki bir açık bulunduğunda saldırganın elde edeceği etki alanını azaltır.

Simetrik şifreleme

Simetrik şifrelemede aynı gizli anahtar şifreleme ve çözme işlemlerinin temelidir.

Genellikle yüksek hacimli verinin korunmasında etkilidir.

Ana sorun anahtarın taraflar arasında güvenli biçimde paylaşılmasıdır.

Asimetrik şifreleme

Asimetrik şifrelemede matematiksel olarak ilişkili açık ve özel anahtar çifti kullanılır.

Açık anahtar paylaşılabilir. Özel anahtar gizli tutulur.

Bu yapı:

  • dijital imza,
  • anahtar değişimi,
  • kimlik doğrulama

gibi işlemlerde kullanılır.

Pratik güvenli haberleşme protokolleri çoğunlukla asimetrik ve simetrik teknikleri birlikte kullanır.

Özet işlevleri

Kriptografik hash işlevi girdiden sabit uzunluklu özet üretir.

Şifreleme ile hash aynı şey değildir.

Şifreleme geri çözülebilir bir dönüşüm olarak tasarlanır.

Kriptografik hash ise tek yönlü kullanım amaçlar.

Hash değerleri bütünlük denetiminde, dijital imzalarda ve parola saklama yapılarının bazı bileşenlerinde kullanılabilir.

Bilgisayar virüsleri

Virüs başka bir çalıştırılabilir içeriğe bağlanarak veya çalışma ortamına yerleşerek çoğalmaya çalışan kötü amaçlı yazılımdır.

Virüsün yalnız dosya uzantısı veya program adı üzerinden tanımlanması yeterli değildir. Temel özellik yayılmak için başka içerik veya yürütme mekanizmasından yararlanmasıdır.

Bilgisayar kurtları

Worm, ağ üzerinden kendini yayabilen kötü amaçlı yazılım sınıfıdır.

Virüsten önemli farkı yayılmak için kullanıcının başka bir dosyayı kopyalamasına veya virüs taşıyan bir programı dağıtmasına ihtiyaç duymayabilmesidir.

Modern tehdit ortamında ransomware, credential stealing, kernel exploit ve supply-chain saldırıları gibi başka zararlı yazılım ve saldırı sınıfları da önemlidir.

İşletim sistemi bunlara karşı tek başına tam güvenlik sağlayamaz. Ancak şu mekanizmalar saldırı yüzeyini azaltır:

  • süreç izolasyonu,
  • bellek koruması,
  • ayrıcalık ayrımı,
  • erişim denetimi,
  • güvenli güncelleme,
  • kod imzalama,
  • yürütme izinleri,
  • sandbox,
  • denetim kayıtları.

Ünite 8: Aygıt Sürücüleri

Aygıt sürücüsünün görevi

Aygıt sürücüsü belirli bir donanım veya aygıt sınıfını işletim sisteminin ortak G/Ç modeline bağlayan yazılım bileşenidir.

Uygulama:

read()

çağrısını yapabilir.

Dosya sistemi veya G/Ç katmanı bu isteği ilgili sürücüye kadar iletir.

Sürücü ise bunu donanımın anlayacağı:

  • yazmaç işlemleri,
  • DMA tanımları,
  • kuyruk girdileri,
  • aygıt komutları

haline dönüştürür.

Bu nedenle sürücü, genel işletim sistemi arayüzü ile donanıma özgü gerçekleştirim arasındaki sınırdır.

Sürücülerin çekirdek içindeki konumu

Birçok sürücü çekirdek ayrıcalıklarıyla çalışır.

Bu durum performans ve donanım erişimi açısından gereklidir ancak hata etkisini büyütür.

Bir çekirdek sürücüsündeki:

  • geçersiz bellek erişimi,
  • race condition,
  • kilitlenme,
  • yanlış DMA adresi

yalnız uygulamayı değil tüm sistemi etkileyebilir.

Bu nedenle sürücü kodunda kaynak yaşam döngüsü, eşzamanlama ve hata yolları özellikle önemlidir.

Aygıt sınıfları

Unix/Linux geleneğinde iki temel aygıt sınıfı öne çıkar.

Character device, veriyi bayt veya akış mantığında sunar.

Block device, veriyi adreslenebilir bloklar halinde sunar.

Terminal, seri aygıt ve çeşitli denetim aygıtları karakter aygıtı olarak modellenebilir.

SSD ve disk gibi depolama aygıtları blok aygıt modeline bağlanır.

Modern Linux sürücü modeli bundan çok daha geniştir. PCI, USB, platform aygıtları, ağ, grafik, giriş, medya ve diğer alt sistemler kendi çerçevelerini kullanır. Güncel Linux çekirdek belgeleri sürücü modeli, DMA, PCI, USB, Virtio ve çeşitli veri yolu alt sistemlerini ayrı API katmanları olarak ele almaktadır. (cdn.kernel.org)

Aygıt dosyaları

Unix geleneğinde birçok aygıt /dev altında dosya benzeri nesnelerle temsil edilir.

Örneğin kullanıcı alanındaki program bir aygıtı open() ile açabilir ve uygun olduğunda read(), write() veya ioctl() gibi işlemler kullanabilir.

Bu modelin güçlü yanı uygulamaya ortak bir arayüz sunmasıdır.

Her aygıtın sıradan dosya gibi davranması gerekmez. Ağ arabirimleri ve grafik aygıtları gibi alt sistemler daha özel API'lere sahip olabilir.

Aygıtın sisteme bağlanması

Modern sürücü mimarisinde sürücünün görevi yalnız modül yüklendiğinde belirli bir init işlevi çalıştırmak değildir.

Aygıt ve sürücünün eşleştirilmesi veri yolu ve aygıt modeli üzerinden yapılabilir.

Örneğin:

  • PCI kimlikleri,
  • USB kimlikleri,
  • firmware tabloları,
  • Device Tree,
  • ACPI

gibi mekanizmalar donanımın tanınmasında kullanılabilir.

Sürücü uygun aygıtla eşleştiğinde kaynaklarını edinir ve aygıtı kullanıma hazırlar.

Kaynak yönetimi

Sürücü tipik olarak şu kaynakları yönetebilir:

  • MMIO bölgeleri,
  • kesilmeler,
  • DMA tamponları,
  • saat kaynakları,
  • güç durumları,
  • aygıt kuyrukları,
  • çekirdek belleği.

Başlatma işleminin herhangi bir aşaması başarısız olabilir.

Bu nedenle daha önce alınan kaynakların ters sırayla güvenli şekilde serbest bırakılması gerekir.

Kaynak yaşam döngüsü sürücü güvenilirliğinin temelidir.

Dinamik bellek

Çekirdek kodu da dinamik bellek kullanabilir ancak kullanıcı alanındaki bellek kullanımından farklı kurallara tabidir.

Linux bağlamında kmalloc() ve vmalloc() gibi mekanizmalar farklı bellek özellikleri sunar.

kmalloc() ile alınan alan çekirdek sanal adres uzayında bitişiktir ve belirli kullanım türlerinde fiziksel düzen bakımından ek garantiler sağlayabilir.

vmalloc() ise sanal olarak bitişik bir alan oluşturabilir ancak fiziksel sayfaların bitişik olması gerekmez.

Bu ayrım özellikle DMA için önemlidir.

MMIO

Modern aygıtların denetim yazmaçları sıklıkla fiziksel adres uzayına eşlenir.

Sürücü bu alanı çekirdek sanal adres uzayına eşledikten sonra özel MMIO erişim yordamlarıyla kullanır.

Normal RAM erişimi ile MMIO erişimi aynı kabul edilmemelidir.

Donanım sıralaması, bariyerler ve mimariye özgü erişim kuralları önem taşıyabilir.

Kesilme yordamları

Aygıt işlemi tamamlandığında kesilme üretebilir.

Sürücü kesilme hizmet yordamında:

  • kesilme kaynağını doğrular,
  • aygıt durumunu işler,
  • gerekirse aktarımı tamamlar,
  • bekleyen çalışmayı uyandırır.

Kesilme bağlamında uzun süren işlem yapılmaması önemlidir.

Daha ağır işler workqueue veya ilgili alt sistemin ertelenmiş çalışma mekanizmalarına aktarılabilir.

DMA

Yüksek hızlı aygıtların veri transferini CPU üzerinden kopyalamak verimsizdir.

Sürücüler DMA ile aygıtın belleğe doğrudan veri aktarmasını sağlayabilir.

Ancak sürücü doğrudan sıradan bir sanal adresi aygıta veremez.

DMA eşleme katmanı:

  • CPU adres alanı,
  • fiziksel bellek,
  • aygıt adres alanı

arasındaki gerekli dönüşümü yönetir.

IOMMU bulunan sistemlerde aygıtın görebildiği adres ayrıca çevrilebilir. Bu yapı hem sanallaştırma hem de erişim sınırlandırması açısından önemlidir. (docs.kernel.org)

Character driver işlemleri

Karakter aygıtlarında tipik kullanıcı işlemleri şunlardır:

  • open,
  • release/close,
  • read,
  • write,
  • poll,
  • mmap,
  • ioctl.

Her sürücünün bunların tümünü sağlaması gerekmez.

ioctl() standart okuma/yazma modeline uymayan aygıt denetim işlemleri için kullanılabilir. Ancak kullanıcı-çekirdek ABI'sinin dikkatli tasarlanması gerekir.

Blok sürücüler

Blok aygıt sürücüsü dosya sisteminden gelen mantıksal blok isteklerini fiziksel depolama aygıtının komutlarına dönüştürür.

Modern depolama aygıtlarında çoklu kuyruklar ve paralel komut yürütme önemlidir.

Bu nedenle eski tek request() kuyruğu üzerine kurulmuş blok sürücüsü örnekleri güncel Linux çekirdek mimarisini temsil etmez.

Kalıcı kavram şudur:

dosya sistemi isteği
       ↓
blok katmanı
       ↓
istek kuyrukları
       ↓
aygıt sürücüsü
       ↓
donanım

Sürücülerde eşzamanlama

Aynı sürücü kodu:

  • kullanıcı süreçleri,
  • kernel worker'lar,
  • kesilme yordamları,
  • farklı işlemci çekirdekleri

tarafından eşzamanlı çalıştırılabilir.

Bu nedenle sürücü tasarımında:

  • spinlock,
  • mutex,
  • atomic işlemler,
  • reference counting,
  • memory ordering

gibi konular doğrudan önem taşır.

Bir aygıt sürücüsü bu açıdan süreç yönetimi, eşzamanlama, bellek yönetimi ve G/Ç konularının birleştiği noktadır.

Ünite 9: Dağıtılmış İşlem ve Ağ İletişimi

Dağıtılmış işlem

Bir bilgisayarın başka bir bilgisayarın kaynaklarından ağ üzerinden yararlanması işletim sisteminin yerel kaynak yönetimini ağ ortamına genişletir.

Paylaşılan kaynak:

  • dosya,
  • yazıcı,
  • servis,
  • veri tabanı,
  • hesaplama hizmeti

olabilir.

Dağıtılmış sistemlerde fiziksel konum kullanıcıdan kısmen gizlenebilir. Ancak ağ gecikmesi, bağlantı kesilmesi ve uzak düğüm arızaları yerel sistemde bulunmayan yeni hata durumları oluşturur.

TCP/IP katmanları

İnternet iletişimi katmanlı yapı üzerine kuruludur.

Basitleştirilmiş model:

Uygulama
   ↓
TCP / UDP
   ↓
IP
   ↓
Bağlantı katmanı
   ↓
Fiziksel ağ

Her katman üst katmana belirli bir hizmet sunar.

Katmanlama ağ donanımının ayrıntılarını uygulamadan ayırır.

IP

Internet Protocol paketlerin ağlar arasında taşınmasını sağlar.

IP temel olarak:

  • adresleme,
  • paket yönlendirme,
  • ağlar arası iletim

işlevlerini üstlenir.

IP teslim garantisi veren bir taşıma protokolü değildir.

Güncel İnternet mimarisinde hem IPv4 hem IPv6 önemlidir. IPv6, RFC 8200 ile Internet Standard olarak tanımlanmıştır. (rfc-editor.org)

TCP

TCP bağlantı yönelimli bir taşıma protokolüdür.

Uygulamaya güvenilir bir bayt akışı sunar.

Başlıca özellikleri:

  • sıra denetimi,
  • kayıp verinin yeniden iletilmesi,
  • akış denetimi,
  • tıkanıklık denetimi,
  • bağlantı durumu yönetimidir.

Bir uygulama mesaj sınırlarının TCP tarafından korunacağını varsaymamalıdır. TCP bir byte stream sağlar.

TCP'nin güncel temel belirtimi RFC 9293'tür. (rfc-editor.org)

UDP

UDP bağlantısız datagram hizmeti sunar.

TCP'deki:

  • bağlantı kurulumu,
  • güvenilir sıralı teslim,
  • yeniden iletim

mekanizmalarını aynı biçimde sağlamaz.

Bu nedenle protokol daha küçük bir taşıma katmanı mekanizmasına sahiptir.

UDP'nin kullanılması otomatik olarak "daha iyi performans" anlamına gelmez. Uygulamanın güvenilirlik, sıra, yeniden iletim veya congestion control ihtiyacı varsa bunların başka bir katmanda ele alınması gerekir.

Port numaraları

IP adresi hedef sistemi belirler.

Port numarası ise sistem içindeki iletişim uç noktasını ayırt etmeye yardımcı olur.

Bir ağ bağlantısını düşünürken temel tanımlayıcılar arasında:

kaynak IP
kaynak port
hedef IP
hedef port
protokol

bulunur.

TCP ve UDP port alanları 16 bittir.

Socket

Socket, uygulamanın işletim sisteminin ağ iletişim hizmetlerine eriştiği temel soyutlamalardan biridir.

Unix socket API'sinde ağ iletişimi bir descriptor üzerinden ele alınabilir.

Bu yaklaşım dosya G/Ç ile ağ G/Ç arasında belirli bir arayüz benzerliği sağlar.

TCP sunucu yapısı

Tipik TCP sunucu akışı:

socket()
   ↓
bind()
   ↓
listen()
   ↓
accept()
   ↓
read/write
   ↓
close()

socket() iletişim uç noktası oluşturur.

bind() yerel adres ve port ile ilişki kurar.

listen() soketi bağlantı kabul eden duruma geçirir.

accept() bekleyen bağlantılardan birini kabul eder ve bu bağlantıya özgü yeni bir descriptor sağlar.

Dinleme soketi yeni istemcileri kabul etmeye devam edebilir.

TCP istemci yapısı

Tipik istemci akışı:

socket()
   ↓
connect()
   ↓
read/write
   ↓
close()

connect() istemcinin uzak sunucuyla bağlantı kurmasını başlatır.

Bağlantı kurulduktan sonra iki yönlü veri aktarımı yapılabilir.

Eşzamanlı sunucular

Bir sunucu yalnız bir istemciye hizmet verirken diğer istemcileri bekletirse ölçeklenebilirliği düşer.

Klasik Unix modelinde her bağlantı için yeni süreç oluşturmak mümkündür.

Başka modeller de vardır:

  • thread-per-connection,
  • thread pool,
  • event-driven I/O,
  • asynchronous I/O.

Yüksek bağlantı sayısında her bağlantı için ayrı işletim sistemi thread'i oluşturmak her zaman en iyi çözüm değildir.

Doğru model:

  • bağlantı sayısı,
  • iş yükü türü,
  • bekleme oranı,
  • gecikme hedefi,
  • işlem maliyeti

gibi özelliklere bağlıdır.

UDP soketleri

UDP bağlantısız iletişimde sunucunun TCP'deki gibi listen() ve accept() kullanması gerekmez.

Temel işlemler arasında:

sendto()
recvfrom()

bulunur.

Her datagram kendi hedef veya kaynak adres bilgisiyle işlenebilir.

Bu yapı kısa istek-yanıt protokollerinde yararlı olabilir.

DNS

İnsanların kullandığı alan adlarının ağ adreslerine çevrilmesini Domain Name System sağlar.

Örneğin uygulama:

example.org

adını kullanabilir.

İletişim kurulabilmesi için bu adın uygun ağ adreslerine çözülmesi gerekir.

DNS dağıtık ve hiyerarşik bir adlandırma sistemidir.

DNS yalnızca basit bir "alan adı -> IP" tablosu değildir. Farklı kayıt türleri, yetkili sunucular, önbellekleme ve delegasyon mekanizmaları içerir.

Ağ iletişiminde hata modeli

Yerel bir işlev çağrısı ile uzak sistem çağrısı aynı hata modeline sahip değildir.

Ağ iletişiminde:

  • paket kaybı,
  • gecikme,
  • bağlantı kopması,
  • uzak sistemin çökmesi,
  • zaman aşımı,
  • kısmi veri aktarımı

oluşabilir.

Bu nedenle dağıtık sistemlerde "yanıt gelmedi" bilgisi tek başına uzak işlemin çalışıp çalışmadığını kesin olarak söylemeyebilir.

Bu ayrım güvenilir dağıtık yazılım tasarımının temelidir.

NFS

Network File System, uzak dosya sistemlerinin ağ üzerinden kullanılmasını sağlayan dağıtık dosya sistemi ailesidir.

Amaç uzak dosyaları yerel dosya sistemi hiyerarşisinin doğal bir parçası gibi sunabilmektir.

Bu yaklaşım:

uygulama
   ↓
VFS
   ↓
yerel FS veya NFS
   ↓
ağ
   ↓
uzak dosya sunucusu

şeklinde düşünülebilir.

Modern NFS sürümleri klasik ilk NFS tasarımlarından önemli ölçüde gelişmiştir. NFSv4.1 için temel protokol belirtimlerinden biri RFC 8881'dir.

VFS ve uzak dosya sistemleri

Sanal dosya sistemi katmanı yerel ve ağ tabanlı farklı dosya sistemlerini ortak bir ad uzayına bağlayabilir.

Linux VFS, kullanıcı programlarının open(), read(), write() ve benzeri işlemlerini belirli dosya sistemi gerçekleştirimlerinden soyutlar. (docs.kernel.org)

Bu soyutlama işletim sistemlerinin genel tasarım anlayışını tekrar gösterir:

Uygulamaya kararlı ve yalın bir mantıksal arayüz sunulur. Fiziksel veya protokole özgü ayrıntılar alt katmanlarda çözülür.

Genel Kavramsal Çerçeve

İşletim sistemi konuları ilk bakışta birbirinden bağımsız görünebilir. Gerçekte tek bir kaynak yönetimi problemi etrafında birleşirler.

Bir program diskten veri okumak istediğinde şu zincir oluşabilir:

uygulama
   ↓
sistem çağrısı
   ↓
dosya sistemi
   ↓
page cache
   ↓
blok G/Ç
   ↓
aygıt sürücüsü
   ↓
DMA
   ↓
depolama aygıtı
   ↓
kesilme
   ↓
görev yöneticisi
   ↓
uygulamanın yeniden çalışması

Bu tek işlem sırasında:

  • sistem çağrısı,
  • kullanıcı/çekirdek modu geçişi,
  • dosya sistemi,
  • bellek yönetimi,
  • G/Ç yönetimi,
  • DMA,
  • kesilme,
  • süreç durumları,
  • işlemci planlama

birlikte çalışır.

İşletim sistemleri dersinin asıl bütünlüğü burada ortaya çıkar.

Bellek yönetimindeki sayfa tablosu yalnız adres çevirmek için değildir. Aynı zamanda koruma sağlar.

Kesilme yalnız G/Ç konusu değildir. Süreç planlamasını tetikleyebilir.

Dosya sistemi yalnız diskte veri tutmaz. Önbellek nedeniyle ana bellek yönetimiyle doğrudan ilişkilidir.

Thread yalnız planlama birimi değildir. Paylaşılan bellek nedeniyle eşzamanlama problemi doğurur.

Socket yalnız ağ programlama aracı değildir. İşletim sisteminin süreçlere sunduğu çekirdek hizmetlerinden biridir.

Aygıt sürücüsü yalnız donanım kodu değildir. Kesilme, DMA, bellek, eşzamanlama ve güvenlik kurallarının aynı yerde uygulanmasını gerektirir.

Bu nedenle işletim sistemi, birbirinden bağımsız yardımcı programlardan oluşan bir paket olarak değil, ortak kaynakların kontrollü kullanımını sağlayan bütünleşik bir sistem olarak düşünülmelidir.

Bu sayfanın QR kodu