Semaphore ve Mutex: Ortak Kaynakları Paylaşmanın İki Farklı Yolu

Birden fazla thread aynı veriye, dosyaya veya bağlantıya aynı anda ulaşmak istediğinde küçük bir trafik kaosu doğar. Bu kaosu yönetmek için kullanılan en temel araçlardan ikisi mutex ve semaphore’dur. İkisi de erişimi sınırlar; ancak mutex tek anahtarlı bir oda kapısı gibi davranırken semaphore belirli sayıda araç kabul eden bir otoparka benzer.

semaphore-ve-mutex-16

Devamı...

Process Scheduler Algoritmaları: CPU Zamanını Kim Hak Ediyor?

Bilgisayarınızda müzik çalarken kod derleyebiliyor, tarayıcıda sekmeler arasında dolaşabiliyor ve arka planda dosya indirebiliyorsanız bunu CPU’nun gizli trafik polisi olan process scheduler’a borçlusunuz. İşlemci aynı anda sınırlı sayıda işi yürütebildiği için scheduler, hazır durumdaki process’lerden hangisinin ne zaman ve ne kadar süre çalışacağını belirler. Kısacası soru şudur: CPU zamanını kim hak ediyor?

process-scheduler-algoritmalari-88

Devamı...

Pipelining: CPU Aynı Anda Nasıl Birden Fazla Komut İşler?

Bir CPU’nun aynı anda birden fazla komut çalıştırdığını duyduğumuzda, işlemcinin düzinelerce eli olan bir robot gibi davrandığını düşünebiliriz. Gerçekteyse pipelining, tek bir işi parçalara ayırıp farklı komutların farklı parçalarını eş zamanlı yürütme tekniğidir. Bir otomobil fabrikasında bir araç boyanırken diğerinin motorunun takılması gibi, işlemci de bir komutu çözerken sıradaki komutu bellekten getirebilir.

Devamı...

Out-of-Order Execution: İşlemci Program Sırasını Neden Bazen Umursamaz?

Bir programdaki komutlar belirli bir sırayla yazılır; fakat modern işlemciler bu sıraya harfiyen uymak zorunda değildir. Sonuç değişmediği sürece hazır olan komutları erkenden çalıştırabilirler. Out-of-order execution, yani sıra dışı yürütme, işlemcinin boş boş beklemek yerine komutlar arasında küçük bir lojistik operasyon yürütmesidir.

out-of-order-19

Devamı...

NUMA Mimarisi: RAM Her Çekirdeğe Gerçekten Aynı Uzaklıkta mı?

Modern bir sunucuda bütün RAM modülleri aynı anakarta takılı olsa da işlemci çekirdekleri açısından eşit uzaklıkta değildir. NUMA, yani Non-Uniform Memory Access, tam olarak bu gerçeği ifade eder: Bir çekirdeğin bazı bellek bölgelerine erişimi hızlı ve ucuzken diğerlerine erişimi daha yavaş olabilir. Kısacası RAM ortak görünür, fakat ona giden yolların uzunluğu aynı değildir.

Devamı...

MMU ve Sanal Adresleme: CPU Gerçek Belleği Nasıl Buluyor?

Bir program bellekteki 0x7FFF1234 adresine eriştiğinde CPU doğrudan RAM’in o noktasına koşmaz. Çünkü programın gördüğü adres, çoğunlukla fiziksel bir konum değil, işletim sistemi tarafından oluşturulmuş sanal bir adrestir. CPU içindeki Bellek Yönetim Birimi (MMU) bu adresi tercüme ederek gerçek RAM konumunu bulur. Kısacası MMU, belleğin simultane tercümanıdır; üstelik yanlış çeviri yaparsa program değil, bütün sistem homurdanabilir.

Devamı...

Memory-Mapped Files: Dosyalar Nasıl Bellekteymiş Gibi Davranır?

Büyük bir dosyanın içeriğine erişmek için genellikle read() çağrıları, tamponlar ve döngüler düşünürüz. Memory-mapped file yaklaşımıysa dosyanın belirli bir bölümünü sürecin sanal adres alanına bağlar. Böylece program, dosyayı gerçekten RAM’e bütünüyle yüklemeden ona sıradan bir bellek dizisiymiş gibi erişebilir. İşin arkasındaki sihir değil; sanal bellek, sayfa tabloları ve işletim sisteminin sayfa önbelleğidir.

Devamı...

LRU, LFU ve CLOCK: İşletim Sistemi Hangi Sayfayı Bellekten Atıyor?

Bir program çalışırken ihtiyaç duyduğu bütün sayfalar fiziksel belleğe sığmayabilir. İşletim sistemi bu durumda disk ile RAM arasında küçük bir sandalye kapmaca oyunu oynar: Yeni sayfa gelecek, fakat boş çerçeve yoksa içerideki sayfalardan biri çıkarılmalıdır. Peki kurban kim olacak? LRU, LFU ve CLOCK algoritmaları aynı soruya farklı ipuçlarıyla cevap verir.

Devamı...

Interrupt Sistemleri: Donanım İşletim Sisteminin Dikkatini Nasıl Çeker?

interrupt-sistemleri-donanim-62

Bilgisayarınızın işlemcisi milyonlarca komutu yürütürken klavyede bir tuşa bastığınızı nasıl fark eder? İşlemcinin sürekli “Klavye hazır mı, ağdan veri geldi mi?” diye sorması mümkün olsa da oldukça verimsizdir. Interrupt, yani kesme sistemi, donanımın işlemciye nazikçe değil, adeta omzuna dokunarak “Önemli bir olay oldu!” demesini sağlar.

Devamı...

DMA: İşlemcinin Üzerinden Veri Taşıma Yükünü Alan Kahraman

Bir diskten belleğe megabaytlarca veri aktarırken işlemcinin her baytı tek tek taşıdığını düşünün. Bu, kargo şirketinin yöneticisinin kamyonu bırakıp bütün kutuları kendisinin taşımasına benzerdi. Direct Memory Access (DMA), veri aktarımını özel bir denetleyiciye devrederek işlemciyi asıl işi olan komut yürütme için serbest bırakır. Ancak işlemci tamamen devre dışı kalmaz; aktarımı başlatır, sonucunu takip eder ve gerektiğinde hatalarla ilgilenir.

dma-islemcinin-uzerinden-35

Devamı...

Deadlock Teorisi: Dört Koşul Sistemi Nasıl Kilitler?

Bir restoranda iki aşçı düşünün: Birinin tava, diğerinin bıçak tuttuğunu; fakat ikisinin de yemeği tamamlamak için diğer araç gerece ihtiyaç duyduğunu hayal edin. Kimse elindekini bırakmazsa mutfak sonsuza kadar bekler. İşletim sistemlerinde bu tatsız tabloya deadlock, yani kilitlenme denir.

Devamı...

Copy-on-Write: Kopyalamadan Kopya Oluşturmanın Akıllı Yolu

Bir nesnenin kopyasını çıkarmak çoğu zaman masum görünür: bellekte yeni bir alan ayır, verileri taşı ve devam et. Ancak yüzlerce megabaytlık verilerle çalışıyorsak bu işlem hem zaman hem bellek tüketir. Copy-on-Write, kısaca CoW, “Gerçekten değiştirmeyeceksen neden kopyalıyorsun?” diyerek iki kopyanın aynı belleği geçici olarak paylaşmasını sağlar.

Devamı...

Condition Variable: Thread’ler Birbirini Nasıl Bekler?

Bir thread’in sürekli “Hazır mı? Hazır mı? Şimdi hazır mı?” diye kontrol yapması, işlemciyi gereksiz yere meşgul eden dijital bir sabırsızlıktır. Condition variable, thread’lerin belirli bir koşul gerçekleşene kadar verimli biçimde uyumasını ve koşul değiştiğinde yeniden çalışmasını sağlayan bir senkronizasyon aracıdır.

Devamı...

Branch Prediction’ın İç Dünyası: CPU Geleceği Nasıl Tahmin Ediyor?

branch-predictionin-ic-50

Modern bir CPU, yalnızca komutları çalıştıran hızlı bir hesap makinesi değildir; aynı zamanda geleceği tahmin etmeye çalışan minik bir falcıdır. Programdaki if, switch ve döngü koşulları işlem akışını değiştirdiğinde CPU, sonucun hesaplanmasını beklemek yerine hangi yolun izleneceğini tahmin eder. Bu mekanizmaya branch prediction, yani dallanma tahmini denir.

Devamı...

ABI Nedir? Derlenen Programların Görünmez Ortak Dili

Bir C fonksiyonunu Rust’tan çağırdığınızda ya da işletim sistemi derlenmiş programınızı çalıştırdığında taraflar kaynak kodu tartışmaz. Bunun yerine; parametrelerin nereye konacağı, sonuçların nasıl döndürüleceği ve belleğin nasıl düzenleneceği gibi önceden belirlenmiş kurallara uyarlar. İşte bu görünmez anlaşmanın adı ABI, yani Application Binary Interface’tir.

Devamı...

Treap: Rastgeleleştirilmiş Dengeli Ağacın Zarif Mantığı

treap-rastgelelestirilmis-dengeli-27

İkili arama ağaçları hızlıdır; tabii ağaç bir bambu dalına dönüşmediği sürece! Sıralı veriler sıradan bir ikili arama ağacına eklendiğinde yapı doğrusal bir liste gibi uzayabilir. Treap, bu sorunu katı dengeleme kuralları yerine rastgelelik kullanarak çözer. İsmi de iki yapının birleşiminden gelir: tree ve heap. Sonuç, şaşırtıcı derecede basit ama beklenen performansı oldukça güçlü bir veri yapısıdır.

Devamı...

Tip Sistemlerinin Evrimi: Weak Typing’den Dependent Type’lara

Tip sistemleri, programlarımızın hangi değerlerle hangi işlemleri yapabileceğini belirleyen görünmez trafik kurallarıdır. İlk bakışta yalnızca “bu değişken sayı mı, metin mi?” sorusuyla ilgileniyor gibi görünürler. Oysa weak typing’den dependent type’lara uzanan yolculuk; hataları ne zaman yakaladığımızı, kod hakkında neleri kanıtlayabildiğimizi ve derleyiciye ne kadar sorumluluk verdiğimizi anlatır.

Devamı...

Suffix Automaton: Bir Metnin Bütün Alt Dizelerini Sıkıştırarak Temsil Etmek

Elimizde uzun bir metin olduğunu ve bu metindeki bütün bitişik alt dizeleri saklamak istediğimizi düşünelim. Uzunluğu $n$ olan bir metin, en fazla $n(n+1)/2$ farklı konum aralığı içerir. Hepsini ayrı ayrı depolamak karesel bir felakete dönüşebilir. Suffix Automaton, yani son ek otomatı, aynı bilgiyi yalnızca $O(n)$ durum ve geçişle temsil eden zarif bir veri yapısıdır.

suffix-automaton-bir-13

Devamı...

Structural Typing ve Nominal Typing: “Neyi Biliyorsun?” mu “Kimsin?” mi?

Bir nesne kapıya geldiğinde tip sistemi ona iki farklı soru sorabilir: “Gerekli özelliklere sahip misin?” veya “Hangi sınıfa mensupsun?” Structural typing ilk soruyla, nominal typing ise ikinci soruyla ilgilenir. Bu ayrım yalnızca akademik bir sınıflandırma değildir; kodun yeniden kullanılabilirliğini, güvenliğini ve API tasarımını doğrudan etkiler.

structural-typing-ve-39

Devamı...

Sparse Table: Değişmeyen Aralık Sorgularını O(1)’de Cevaplamak

Bir dizi üzerinde tekrar tekrar “şu aralıktaki en küçük eleman nedir?” diye sorulacağını, fakat dizinin hiçbir zaman değişmeyeceğini düşün. Her sorguda aralığı baştan sona dolaşmak gereksiz bir maraton olur. Sparse Table, biraz ön hazırlık yaparak minimum, maksimum ve EBOB gibi değişmeyen aralık sorgularını $O(1)$ sürede cevaplayan zarif bir veri yapısıdır.

Devamı...