Ders 11 / 16
Kesmeler
Dış olayların işlemciye bildirilmesi, bağlam saklama, kesme türleri ve önalımlı çok görevliliğin temeli.
İçindekiler
Önceki dersler işlemciyi kapalı bir sistem olarak ele aldı: komutları getirir, çözer, yürütür ve bir sonrakine geçer. Oysa bir bilgisayar dış dünyayla etkileşir. Klavyeye basılır, diskten okuma tamamlanır, ağdan paket gelir. Bu olayların ne zaman gerçekleşeceği önceden bilinemez.
Bu dersin sorusu şudur: kendi döngüsüyle meşgul olan bir işlemciye, dış dünyada bir şey olduğu nasıl bildirilir?
Yoklama ve Sınırı
Akla ilk gelen çözüm yoklamadır (polling): program, aygıtın durumunu düzenli aralıklarla sorar.
döngü:
aygıt durumunu oku
veri hazır değilse döngüye dön
veriyi işle
Yoklamanın iki maliyeti vardır. Aygıt uzun süre hazır olmazsa, işlemci hiçbir iş üretmeden döner; her sorgu bir bellek erişimi ve birkaç komut harcar. Öte yandan sorgu aralığı seyreltilirse bu kez gecikme artar: olay gerçekleştikten sonra fark edilene kadar geçen süre uzar.
Yoklama her koşulda kötü değildir. Olayın çok sık ve öngörülebilir aralıklarla geldiği durumlarda, kesme işlemenin sabit maliyetinden ucuza gelebilir. Ancak genel çözüm olamaz.
Kesme Mekanizması
Kesme (interrupt), aygıtın işlemciye ilettiği bir sinyaldir. İşlemci bu sinyali aldığında yürüttüğü komutu tamamlar ve akışı kendiliğinden başka bir yere aktarır. Adımlar şunlardır:
- Yürütülmekte olan komut tamamlanır.
- Bağlam saklanır: program sayacı ve gerekli yazmaçlar, akış sonradan kaldığı yerden sürebilsin diye bir kenara yazılır.
- Kesme numarası kullanılarak kesme vektör tablosundan ilgili işleyicinin adresi okunur.
- Program sayacına bu adres yazılır; kesme işleyicisi (interrupt handler) çalışır.
- İşleyici bittiğinde bağlam geri yüklenir ve kesilen program, kesildiğini fark etmeden devam eder.
Kesilen programın bakış açısından hiçbir şey olmamıştır: yazmaçlar aynı, program sayacı beklenen yerdedir. Yalnızca geçen zaman farklıdır.
Bu mekanizmanın maliyeti sıfır değildir. Bağlam saklama ve geri yükleme birkaç komutluk iş yapar ve önbellek içeriğini bozabilir. Kesme işleyicilerinin kısa tutulması bu yüzden bir tasarım kuralıdır: işleyici yalnızca acil olanı yapar, uzun süren işi sonradan çalışacak bir göreve bırakır.
Kesme Türleri
Akışı kesen olaylar tek türden değildir.
Donanım kesmesi eşzamansızdır: dış aygıttan gelir ve programın hangi komutta olduğu ile ilgisi yoktur. Klavye, disk denetleyicisi, ağ arayüzü ve zamanlayıcı bu sınıftandır.
İstisna (exception) veya tuzak (trap) eşzamanlıdır: yürütülmekte olan komutun kendisi tarafından üretilir. Sıfıra bölme, geçersiz komut, izinsiz bellek erişimi ve sayfa hatası bu sınıftadır. Aynı programı aynı girdiyle yeniden çalıştırmak, istisnayı aynı noktada üretir.
Ayrım pratiktir: eşzamansız bir kesme ertelenebilir, eşzamanlı bir istisna ertelenemez — komut, istisna ele alınmadan tamamlanamaz.
Yazılım kesmesi, programın kendi isteğiyle ürettiği tuzaktır ve işletim sistemi çağrılarının temelidir. Kullanıcı programı, ayrıcalık gerektiren bir iş için (dosya açmak, ağ soketi oluşturmak) doğrudan donanıma erişemez; bunun yerine bir tuzak üretir, ayrıcalıklı kod çalışır ve sonucu döndürür. Kullanıcı kipi ile çekirdek kipi arasındaki sınır bu noktada çizilir.
Zamanlayıcı Kesmesi ve Önalım
Kesmelerin en önemlisi, dış dünyadan değil, işlemcinin kendi zamanlayıcısından gelir. Bu zamanlayıcı düzenli aralıklarla kesme üretir.
Sonucu belirleyicidir: hiçbir program, işlemciyi süresiz elinde tutamaz. Zamanlayıcı kesmesi geldiğinde denetim işletim sistemine geçer; işletim sistemi çalışan programın bağlamını saklar, başka bir programın bağlamını yükler ve akış oradan devam eder. Bu düzene önalımlı (preemptive) çok görevlilik denir.
Önalım olmasaydı, çok görevlilik programların gönüllü işbirliğine kalırdı; sonsuz döngüye giren tek bir program tüm sistemi kilitlerdi. Süreç ve iş parçacığı planlaması, işletim sistemi kavramları kursunda bu temel üzerine kurulur.
Doğrudan Bellek Erişimi
Kesme, aygıtın “hazırım” demesini ucuzlatır; ancak verinin taşınması hâlâ işlemcinin işiyse kazanç sınırlı kalır. Diskten okunan bir bloğu bayt bayt yazmaçlara alıp belleğe yazmak, işlemciyi taşıma işine bağlar.
Doğrudan bellek erişimi (direct memory access), taşımayı ayrı bir denetleyiciye devreder. İşlemci yalnızca isteği tanımlar: kaynak, hedef adres ve uzunluk. Denetleyici aktarımı kendisi yürütür; işlemci bu sırada başka komutlar işler. Aktarım bittiğinde denetleyici bir kesme üretir.
Bu düzen, kesmenin asıl kazancını ortaya çıkarır: işlemci ne veriyi bekler ne de taşır; yalnızca başlatır ve bittiğinde haberdar edilir. Aynı ilke üst katmanlarda da sürer — eşzamansız girdi/çıktı arayüzleri, “isteği ver, sonucu bildirilince al” düzenini yazılım düzeyinde tekrarlar.
Bedeli, paylaşılan bellek üzerinde iki yazıcı bulunmasıdır: denetleyici belleği değiştirirken işlemcinin önbelleğinde o bölgenin eski kopyası durabilir. Tutarlılığın korunması donanım ve sürücü sorumluluğundadır.
Maskeleme ve Öncelik
Kesme işleyicisi çalışırken yeni bir kesme gelebilir. Donanım bu durumu iki araçla yönetir.
Maskeleme: Belirli kesmeler geçici olarak bastırılabilir. Bölünmesi hâlinde tutarsız duruma yol açacak kısa kod parçaları — kritik bölgeler — kesmeler kapalıyken çalışır. Bu sürenin uzun tutulması, sistemin dış olaylara yanıt gecikmesini doğrudan artırır.
Öncelik: Kesmeler önem sırasına göre derecelendirilir; yüksek öncelikli bir kesme, düşük öncelikli bir işleyiciyi kesebilir. İç içe geçen kesmeler, bağlamların yığıt üzerinde birikmesi anlamına gelir.
Tüm kesmelerin bastırılamadığı bir sınıf da vardır: donanım arızası gibi ertelenmesi anlamsız olaylar için ayrılmış maskelenemez kesmeler.
Programa Yansıması
Kesme donanım düzeyinde bir kavramdır, ancak izleri yazılımda görünür. Bir işletim sistemi sinyali, süreç için kesmenin karşılığıdır: akış nerede olursa olsun, kayıtlı işleyici çalışır ve sonra kaldığı yerden devam eder.
import signal, time kesme_sayisi = 0 def zamanlayici_isleyicisi(sinyal_no, cerceve): """Akış nerede olursa olsun bu işlev çalışır ve sonra geri dönülür.""" global kesme_sayisi kesme_sayisi += 1 signal.signal(signal.SIGALRM, zamanlayici_isleyicisi) signal.setitimer(signal.ITIMER_REAL, 0.05, 0.05) # 50 ms'de bir sinyal baslangic = time.perf_counter() sayac = 0 while time.perf_counter() - baslangic < 0.5: # yarım saniyelik yoğun döngü sayac += 1 signal.setitimer(signal.ITIMER_REAL, 0) # zamanlayıcıyı durdur print(kesme_sayisi) # 9 dolayında
Döngüde sinyali bekleyen hiçbir satır yoktur; buna karşın işleyici yaklaşık dokuz kez çalışmıştır. Kesme kavramının ayırt edici yanı budur: denetim, akışın kendisi istemeden aktarılır.
Benzetmenin sınırı da belirtilmelidir. İşletim sistemi sinyalleri donanım kesmesi değildir; çalışma zamanı bunları güvenli noktalarda işler. Yine de akışın dışarıdan kesilmesi fikri aynıdır.
Aynı fikir daha üst katmanlarda da sürer: eşzamansız girdi/çıktı, olay döngüleri ve geri çağrı tabanlı arayüzler, “hazır olduğunda haber ver” ilkesinin yazılım düzeyindeki karşılıklarıdır.
Özet
- Yoklama, aygıt durumunu düzenli sorgular; işlemci zamanı harcar veya gecikme artar.
- Kesme, aygıtın işlemciye ilettiği sinyaldir; işlemci bağlamı saklar, işleyiciyi çalıştırır ve akışı kaldığı yerden sürdürür.
- Donanım kesmeleri eşzamansız, istisnalar eşzamanlıdır; yazılım kesmeleri ise işletim sistemi çağrılarının temelidir.
- Zamanlayıcı kesmesi, hiçbir programın işlemciyi süresiz tutamamasını sağlar ve önalımlı çok görevliliği mümkün kılar.
- Kritik bölgelerde kesmeler maskelenir; maskeleme süresi uzadıkça sistemin yanıt gecikmesi artar.
- Kesme işleyicileri kısa tutulur; bağlam saklama ve geri yükleme maliyetlidir.
Sonraki Adım
Bu konunun geri kalan sorusu, işlemin kendisidir: toplama komutu çalıştığında donanımda ne olur? Sonraki ders, aritmetiğin mantık kapılarıyla nasıl kurulduğunu ve ikiye tümleyen gösteriminin neden çıkarma için ayrı bir devre gerektirmediğini gösterecek.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.