Bir metin dosyasındaki her satırı ayrı bir iş birimi gibi düşünelim: Her satır küçük bir paket, her child process de bu paketi işleyen minik bir işçi. Sistem çağrısı seviyesinde paralel boru hattı kurmanın amacı, bu işçileri fork(), pipe(), dup2(), exec() ve wait() gibi yapı taşlarıyla yönetip çıktıları tek bir satırda birleştirmektir. Bu yaklaşım, shell komutlarını taklit etmekten öte, işletim sisteminin süreç ve dosya tanımlayıcı mantığını gerçekten kavratır.

Devamı...

Bir saldırganın cihazınızı ele geçirdiğini ve LUKS parolasını denediğini düşünün. Normalde yanlış parola yalnızca “erişim yok” demektir; fakat savunmacı aldatma yaklaşımında sistem, belirli sayıda hatadan sonra sanki parola kabul edilmiş gibi davranıp izole bir sahte masaüstü başlatabilir. Bu yazıda bunu kötüye kullanım değil, yalnızca kendi cihazınızda ve laboratuvar ortamında uygulanacak bir güvenlik tasarımı olarak ele alacağız.
Devamı...

Bazen fiziksel bir fareye ya da klavyeye dokunmadan sisteme giriş olayı göndermek isteriz: test otomasyonu, erişilebilirlik araçları, kiosk sistemleri, oyun botu prototipleri veya uzaktan kontrol yazılımları buna örnektir. Linux tarafında bu işin en temiz yollarından biri /dev/uinput aygıtıdır. Kısaca uinput, kullanıcı alanındaki bir programın çekirdeğe “Ben bir input aygıtıyım” demesini ve gerçek donanım gibi olay üretmesini sağlar.
Devamı...

Konteyner denince akla hemen Docker gelir; ama sahnenin arkasında sihirli bir ejderha değil, Linux çekirdeğinin çok ciddi iki mekanizması çalışır: ad alanları ve kontrol grupları. Bu yazıda hazır bir konteyner motoru kullanmadan, kabuk betikleriyle küçük ama öğretici bir motor kuracağız. Amaç üretim ortamına rakip çıkarmak değil; kaputun altındaki pistonları tek tek görmek.
Devamı...
Bir dosya silindiğinde çoğu zaman verinin kendisi anında buharlaşmaz; dosya sisteminin “bu alan artık boş” dediği muhasebe kayıtları değişir. İşte ham disk imajını hexedit ile açıp inode ve blok adreslerini elle okumak, biraz arkeoloji biraz dedektiflik gibidir: kumların altından byte byte hikâye çıkarırız.
Devamı...
Bir sunucuda log, kuyruk, API, veritabanı ve sistem metriklerini aynı anda izlemek bazen dedektiflik oyunu gibidir: ipucu bir yerde akar, hata başka yerde patlar. Bu yazıda kabuk betikleri ve tmux kullanarak ekranı satranç tahtası gibi bölen, her bölmede ayrı bir sürecin canlı çıktısını gösteren eğlenceli ama işe yarar bir izleme konsolu hazırlayacağız.
Devamı...
Prolog dünyasında program yazmak biraz labirentte akıllı bir dedektif gezdirmeye benzer: Dedektif her kapıyı dener, çıkmaz sokak görünce geri döner ve başka bir kapıya yönelir. Bu mekanizmaya geriye izleme denir. Kesme operatörü, yani !, dedektife şunu söyler: Buraya kadar geldiysen artık önceki kapıları kurcalama, bu yoldan devam et. Doğru kullanıldığında arama uzayını küçültür, performansı artırır ve programın niyetini daha net ifade eder.
Devamı...
Prolog’da bazen cevabı bulmak yetmez; tüm cevapları, tüm kombinasyonları, hatta köşede saklanan o utangaç olasılığı da görmek isteriz. İşte fail operatörü burada sahneye çıkar: Sisteme bilinçli olarak başarısızlık dayatır ve Prolog motorunu geri izleme, yani backtracking yapmaya zorlar.

Devamı...

Kod yazmak bazen yemek tarifi uygulamak gibidir: Malzemeler doğru, fırın çalışıyor, ama kek yine de çöker. İşte hata ayıklama ve özellikle izleme yani trace modu, bu çöküşün hangi adımda başladığını görmemizi sağlar. Programın satır satır nasıl ilerlediğini, değişkenlerin hangi değerleri aldığını ve mantığın nerede ters köşe yaptığını takip ederek “bence çalışmalıydı” cümlesini “şurada yanlış düşünmüşüm” seviyesine taşırız.
Devamı...
Linux çekirdeğinin içine küçük, güvenli ve olay odaklı programlar bırakabildiğinizi düşünün; üstelik kernel modülü yazmadan, sistemi yeniden başlatmadan ve çekirdeği yeniden derlemeden. İşte eBPF tam olarak bu büyülü tornavida. Bu yazıda gelen TCP bağlantı isteklerini anlık sayan ve saniyelik değerleri terminalde histogram olarak gösteren mini bir ağ trafiği gözlemcisi tasarlayacağız.
Devamı...

Bir programın dış dünyayla tokalaşmasının en klasik yolu dosyalardır. Kullanıcıdan gelen ham metinler, log kayıtları, CSV benzeri raporlar veya analizden sonra üretilen sonuç belgeleri; hepsi dosya okuma ve yazma işlemleriyle sisteme girer ya da sistemden çıkar. Kısacası dosya işlemleri, bellekte uçuşan veriyi kalıcı ve paylaşılabilir bilgiye dönüştüren köprüdür.
Devamı...
Bir programın çalışırken fikrini değiştirebilmesi kulağa biraz bilim kurgu gibi gelir, değil mi? Dinamik veri tabanı yönetimi tam olarak bunu sağlar: sistem, bellekte tuttuğu gerçekleri ve kuralları çalışma anında ekler, siler ve yeni duruma göre farklı sonuçlar üretir. Özellikle Prolog gibi mantıksal programlama dillerinde assert ve retract, programı sabit bir tarif defteri olmaktan çıkarıp mutfakta karar değiştirebilen bir şefe dönüştürür.
Devamı...
Bir cümleyi okurken beynimiz kelimeleri tek tek saymaz; özne nerede, yüklem ne söylüyor, hangi sözcük hangi görevi üstlenmiş gibi yapısal ilişkileri hızla kurar. Definite Clause Grammars, yani DCG, tam da bu sezgisel süreci mantıksal kurallara dökmenin zarif bir yoludur. Özellikle Prolog dünyasında DCG, insan dilini parçalamak, cümleleri çözümlemek ve sembolik doğal dil işleme sistemleri kurmak için küçük ama güçlü bir laboratuvar gibidir.

Devamı...
Bir programın kullanıcıyla ilk selamlaşması çoğu zaman ekrana yazdırdığı küçücük bir metinle başlar. Mantıksal programlama dünyasında, özellikle Prolog gibi dillerde, bu iş “fonksiyon çağırmak”tan çok “yüklem çalıştırmak” şeklinde düşünülür. Yani ekrana metin basmak, değişkenin değerini görmek veya satır atlamak için sisteme gömülü standart yüklemlerden yararlanırız.
Devamı...
Programlamada aritmetik deyince çoğu dilde x = 2 + 3 yazıp sonucu bekleriz. Prolog ise biraz daha felsefi davranır: Önce sembolleri, terimleri ve ilişkileri düşünür; hesaplama ise özel olarak istendiğinde yapılır. İşte is operatörü tam bu noktada sahneye çıkar: Matematiksel formülü sadece sembolik bir yapı olarak tutmak yerine, gerçekten hesaplar ve kesin sonucu yeni bir değişkene bağlar.
Devamı...

Bir listeyi gezmek, bir dizindeki dosyaları taramak ya da ardışık adımlarla sonuca ulaşmak denince akla genellikle for ve while döngüleri gelir. Özyineleme ise aynı işi farklı bir zihinsel modelle yapar: Bir kural, problemin daha küçük bir sürümünü çözmek için kendini yeniden çağırır. Yani kontrol akışı dışarıdan dönen bir çark gibi değil, iç içe açılan matruşka bebekleri gibi ilerler.
Devamı...
Programlamada bir uygulamanın “akıllı” görünmesini sağlayan şey çoğu zaman çok basit bir sorudur: “Bu doğru mu, değil mi?” Mantıksal karşılaştırma işlemleri; değişkenler veya sabit değerler arasında büyüklük, küçüklük, eşitlik ya da denklik gibi ilişkileri kontrol eder ve sonucu genellikle true veya false olarak üretir. Yani kod dünyasının trafik lambaları gibidirler: geç, dur, bekle!

Devamı...

Birden fazla veriyi tek tek değişkenlerde taşımak, market poşetlerini tek parmakla taşımaya benzer: mümkün ama gereksiz acı verici. Listeler, verileri köşeli parantezler içinde tek bir bütün gibi saklamamızı sağlar: [10, 20, 30]. Daha önemlisi, bu bütünün ilk elemanını baş yani head, geri kalan kısmını ise kuyruk yani tail olarak düşünebiliriz.
Devamı...
Bir labirentte yürüdüğünü düşün: Önünde üç yol var, birini seçiyorsun, ilerliyorsun ve duvara çarpıyorsun. Panik yok! Son karar noktasına geri dönüp denenmemiş diğer yolu seçiyorsun. İşte geriye izleme, yani backtracking, bilgisayarın bu “hmm olmadı, başka kapı deneyelim” refleksidir. Özellikle bulmaca çözme, rota arama, kombinasyon üretme ve kısıt sağlama problemlerinde sistematik şekilde alternatifleri dener.

Devamı...
Bir bilgi tabanınız olduğunu düşünün: içinde gerçekler, kurallar ve biraz da dedektiflik kokan ilişkiler var. Sorgular mekanizması, bu yapıya dışarıdan soru sormamızı sağlar: Bu sonuç doğru mu, yanlış mı, yoksa sistemin bildikleriyle kanıtlanamıyor mu? Kısacası sorgu, mantık motoruna yöneltilen kontrollü bir mercek gibidir; veriyi ezberlemek yerine, sonuç çıkarmayı otomatikleştirir.
Devamı...