Ders 01 / 22
Süreç Listeleme ve Arama
Yirmi dört süreçlik kurgu bir sunucuda gerçekte 14 süreç ağır: örnekleme aralığı 15 saniyeye çıkınca araç 3'ünü, 30 ve 60 saniyede 5'ini kaçırıyor; tek bakış 5–7, ömür ortalaması 7 yanlış tanı veriyor ve ada göre seçim en iyi durumda 9 sürece yanlış dokunuyor.
İçindekiler
Kabuk Programlama kursu bir betiği araca dönüştürdü: argüman arayüzü kazandı, hatalarda durdu, arkasını topladı ve bir zamanlayıcıya verildi. Betik yazmak bir şeyi yaptırmaktır. Sistem yönetimi başka bir işle başlar — önce ne olduğunu görmek. Ve görmenin kendi hataları vardır.
Bu kurs o hataları sayar. İşletim Sistemi Kavramları kursu süreci, çizelgeleyiciyi ve bağlam değiştirmeyi mekanizma olarak ölçmüştü; orada ölçülen şey soyutlamanın bedeliydi. Burada mekanizma yeniden kurulmaz: ölçülen şey operatörün o mekanizmadan ne görebildiğidir.
Kursun Ölçüsü
Her derste üç sayı yan yana durur. Birincisi kâhin (oracle): sistemin gerçek durumu. Kurguyu biz ürettiğimiz için hangi sürecin gerçekten ağır olduğunu biliyoruz. İkincisi araç çıktısı: aracın gösterdiği. Üçüncüsü yanlış tanı (false diagnosis) sayısı: çıktıdan çıkarılan sonucun kâhinle kaç kez çeliştiği.
Kuralın kendisi tek cümledir: bir komutun sayısı gösterdiği satır değil, o satırlardan çıkarılan tanının kaç kez yanlış olduğudur. Tanısı sınanmayan bir çıktı ölçülmemiş sayılır.
- SY1. Gözlem penceresi 600 saniyedir. Bütün süreler modeldeki saniyedir; gerçek zaman ölçülmez.
- SY2. Kurgu sunucuda 24 süreç vardır. Her sürecin gerçek işlemci kullanımı tek bir sayı değil, bir zaman dizisidir.
- SY3. Üç desen vardır: düz (sürekli düşük), ani (altmış saniyede bir, beş saniyelik sıçrama), ağır (sürekli yüksek).
- SY4. Bir süreç, pencere boyunca kullanımı bir kez bile 50’yi aştıysa ağır sayılır. Kâhin bu tanımı bütün 600 saniyeye bakarak uygular; araç yalnız baktığı anlara bakar.
- SY5. İzleme aracı
aralıksaniyede bir bakar ve süreç başına gördüğü en yüksek değeri saklar. Bakışlar arasında olan biteni bilmez. - SY6. Yanlış tanı sayısı, kaçırılan ağır süreçler ile ağır sanılan hafif süreçlerin toplamıdır.
- SY7. İkinci tohum 20260219’dur. Ayrılan tanı sayısı aynı büyüklük düzeninde kalmazsa sonuç kurguya bağlıdır ve öyle yazılır.
Süreç Tablosunu Okumak
Süreç listesini veren komut ps, sürekli tazelenen görünümü veren komut top ya da onun
etkileşimli türevleridir. ps bir anlık kesittir; verdiği liste, komutun koştuğu andaki
süreç tablosudur. Aşağıdaki döküm örnektir, bu sayfa için üretilmiştir ve çalıştırılmamıştır:
$ ps -eo pid,user,ni,pcpu,pmem,etime,comm --sort=-pcpu
PID USER NI %CPU %MEM ELAPSED COMMAND
1128 uygulama 0 71.2 3.1 00:10:00 kuyruk-isleyici
1043 izleme 5 68.4 1.2 00:10:00 olcum-toplayici
1014 uygulama -3 64.9 2.8 00:10:00 rapor-uretici
1092 kok 0 6.1 0.4 00:10:00 yedek-gorevi
1071 yedek 10 3.0 0.2 00:10:00 onbellek-temizleyici
Sütunların çoğu kendini anlatır; ikisi anlatmaz. NI, dersin dördüncüsünde ölçülecek olan
öncelik değeridir. %CPU ise en yanıltıcı sütundur: ps bu değeri sürecin doğumundan
beri geçen süreye böler, yani bir ömür ortalamasıdır. On saat çalışmış bir süreç, son
beş dakikada çekirdeği tek başına tüketse bile bu sütunda düşük görünür.
top aynı sütunu başka türlü hesaplar: iki tazeleme arasında geçen kısa aralığı temsil eder.
İki komut aynı makinede aynı anda çalıştırıldığında aynı süreç için farklı sayılar verir ve
ikisi de doğrudur; farklı zaman aralıklarını ölçüyorlar. Bu ayrım bu dersin ölçtüğü şeyin
tam olarak kaynağıdır.
Kurgu Sunucu
Ölçüm, gerçek bir komuta değil, kursun ortak tanımına dayanır. Gerçek bir sunucuda koşan komutun çıktısı yeniden üretilemez: makine başka, yük başka, saat başka. Kurgu sunucuyu biz ürettiğimiz için kâhini biliyoruz.
"""M03/K03 ortak tanim: kurgu bir sunucu , araclarin urettigi metin ve o metinden cikarilan taninin KAHINLE karsilastirilmasi. Hicbir gercek komut cagrilmaz. """ TOHUM = 20260218 IKINCI_TOHUM = 20260219 DONEM = 600 # gozlem penceresi: 600 saniye def uretec(tohum): d = tohum def sonraki(n): nonlocal d d = (d * 1103515245 + 12345) % 2147483648 return d % n return sonraki KULLANICI = ("kok", "uygulama", "yedek", "izleme") KOMUT = ("veri-alici", "rapor-uretici", "yedek-gorevi", "olcum-toplayici", "kuyruk-isleyici", "onbellek-temizleyici") def surecler(tohum=TOHUM, sayi=24): """Her surec: gercek islemci kullanimi bir ZAMAN DIZISIDIR , tek sayi degil.""" r = uretec(tohum) liste = [] for i in range(sayi): tur = r(10) desen = "duz" if tur < 5 else ("ani" if tur < 8 else "agir") liste.append({"pid": 1000 + i * 7 + r(5), "kullanici": KULLANICI[r(len(KULLANICI))], "komut": KOMUT[r(len(KOMUT))], "desen": desen, "oncelik": r(11) - 5, "bellek": 20 + r(400), "sinyal_yok_sayar": r(10) < 2}) return liste def kullanim(surec, saniye): """Gercek islemci kullanimi , saniye saniye. Kahin bunu bilir; arac bilmez.""" d = surec["desen"] if d == "duz": return 3 + (surec["pid"] + saniye) % 4 if d == "agir": return 60 + (surec["pid"] + saniye) % 25 faz = (saniye + surec["pid"]) % 60 # ani: 60 saniyede bir 5 saniyelik sicrama return 88 + faz if faz < 5 else 2 + faz % 3 S = surecler() print("kurgu sunucu:", len(S), "surec |", {d: sum(1 for s in S if s["desen"] == d) for d in ("duz", "ani", "agir")}) print("gercekte esigi asan surec:", sum(1 for s in S if max(kullanim(s, t) for t in range(DONEM)) >= 50))
kurgu sunucu: 24 surec | {'duz': 10, 'ani': 7, 'agir': 7}
gercekte esigi asan surec: 14
Kâhin 14’tür. Yedi süreç sürekli ağırdır, yedisi ise altmış saniyede bir sıçrar ve sıçradığında eşiği fazlasıyla aşar. Toplam 24 sürecin 14’ü, eşiği pencerenin bir yerinde geçiyor. Bundan sonraki her sayı bu 14’e göre okunur.
Örnekleme Aralığı Tanıyı Belirliyor
İzleme aracının tek ayarı vardır: ne sıklıkla bakacağı. Aralığı büyütmek çıktıyı küçültür ve yükü azaltır. Bunun tanıya ne yaptığı ölçülebilir.
# Ilk blogun uzerine: S, kullanim, DONEM, IKINCI_TOHUM, surecler oradan gelir. def ornekle(surecler_, aralik, pencere=DONEM): """`aralik` saniyede bir bakan izleme araci. Doner: surec basina gorulen en yuksek.""" goruldu = {s["pid"]: 0 for s in surecler_} bakis = 0 for t in range(0, pencere, aralik): bakis += 1 for s in surecler_: goruldu[s["pid"]] = max(goruldu[s["pid"]], kullanim(s, t)) return {"bakis": bakis, "goruldu": goruldu} def gercek_en_yuksek(surecler_, pencere=DONEM): return {s["pid"]: max(kullanim(s, t) for t in range(pencere)) for s in surecler_} def tani_agir_surec(olcum, esik=50): """Ciktidan cikarilan tani: hangi surecler agir.""" return {p for p, v in olcum.items() if v >= esik} ARALIK = (1, 5, 15, 30, 60) def supur(surecler_): gercek = tani_agir_surec(gercek_en_yuksek(surecler_)) satir = [] for a in ARALIK: o = ornekle(surecler_, a) t = tani_agir_surec(o["goruldu"]) satir.append((a, o["bakis"], len(t), len(gercek - t), len(gercek - t) + len(t - gercek))) return len(gercek), satir kahin, satirlar = supur(S) print("aralik bakis uretilen satir gorulen agir kacirilan yanlis tani") for a, bakis, gor, kacan, yanlis in satirlar: print(f"{a:6d} {bakis:5d} {bakis * len(S):14d} {gor:12d}" f" {kacan:9d} {yanlis:11d}") print("kahin (gercekte agir):", kahin, "| toplam surec:", len(S)) print() kahin2, satirlar2 = supur(surecler(IKINCI_TOHUM)) print("ikinci tohum", IKINCI_TOHUM, "- kahin:", kahin2) print(" yanlis tani:", {a: y for a, _, _, _, y in satirlar2}) print(" ilk tohum :", {a: y for a, _, _, _, y in satirlar})
aralik bakis uretilen satir gorulen agir kacirilan yanlis tani
1 600 14400 14 0 0
5 120 2880 14 0 0
15 40 960 11 3 3
30 20 480 9 5 5
60 10 240 9 5 5
kahin (gercekte agir): 14 | toplam surec: 24
ikinci tohum 20260219 - kahin: 12
yanlis tani: {1: 0, 5: 0, 15: 5, 30: 6, 60: 7}
ilk tohum : {1: 0, 5: 0, 15: 3, 30: 5, 60: 5}
Bir ve beş saniyede bir bakan araç 14 ağır sürecin 14’ünü de görüyor: yanlış tanı sıfır. Aralık 15 saniyeye çıktığında 3, 30 ve 60 saniyede 5 süreç kaçıyor. Kaçanlar hep aynı sınıftır — altmış saniyede bir, beş saniye boyunca yükselenler. Otuz saniyede bir bakan bir araç, beş saniyelik bir sıçramayı yakalamak zorunda değildir; çoğu zaman yakalamaz.
Araç yalan söylemiyor. Baktığı anda o süreç gerçekten hafifti. Yanlış olan şey çıktı değil, çıktıdan çıkarılan tanıdır: “listede yok, demek ki sorun değil.”
İkinci sütun ikinci iddiayı taşır. Aralık 1’de araç 14.400 satır üretiyor, aralık 60’ta 240. Satır sayısı altmış katına çıkarken yanlış tanı 5’ten 0’a iniyor — ama bu iki sayının ilişkisi doğrusal değildir: 2.880 satır da 14.400 satır kadar iyi tanı veriyor. Beş saniyeden sonra eklenen her satır tanıya hiçbir şey katmıyor.
İkinci tohumda kâhin 12’ye düşüyor ve yanlış tanı 5, 6, 7 çıkıyor. Sayılar aynı değil; yön ve büyüklük düzeni aynı — sıfırdan başlıyor, aralıkla birlikte tek haneli bir bandın içinde büyüyor. Ayakta kalan sonuç şudur: aralığı büyütmek kaçırılan süreç üretir. Kaç tanesinin kaçacağı kurguya bağlıdır.
Tek Bakış ile Ömür Ortalaması
Örnekleme aralığı çok bakışın sorunudur. Operatörün en sık yaptığı şey ise tek bakıştır:
bir kez ps çalıştırmak. Bunun ve ps sütununun kendi ortalamasının bedeli ayrı ölçülür.
# Onceki bloklarin uzerine: S, kullanim, DONEM ve tani_agir_surec oradan gelir. GERCEK = tani_agir_surec({s["pid"]: max(kullanim(s, t) for t in range(DONEM)) for s in S}) def anlik(surecler_, t): """Tek bakista okunan deger: o anda ne kullaniyordu.""" return {s["pid"]: kullanim(s, t) for s in surecler_} def omur_ortalamasi(surecler_, pencere=DONEM): """Surecin dogumundan beri ortalamasi. Sicramayi seyreltir.""" return {s["pid"]: sum(kullanim(s, t) for t in range(pencere)) // pencere for s in surecler_} okumalar = [(f"anlik t={t:<3d} ", anlik(S, t)) for t in (0, 3, 30, 300)] okumalar.append(("omur ortalamasi ", omur_ortalamasi(S))) print("okuma bicimi gorulen agir kacirilan yanlis tani") for ad, olcum in okumalar: t_ = tani_agir_surec(olcum) print(f" {ad}{len(t_):10d} {len(GERCEK - t_):9d}" f" {len(t_ - GERCEK) + len(GERCEK - t_):11d}") print("kahin:", len(GERCEK), "agir surec |", len(S), "surecin icinde")
okuma bicimi gorulen agir kacirilan yanlis tani anlik t=0 9 5 5 anlik t=3 8 6 6 anlik t=30 7 7 7 anlik t=300 9 5 5 omur ortalamasi 7 7 7 kahin: 14 agir surec | 24 surecin icinde
Tek bakış, bakılan ana göre 5 ile 7 arasında yanlış tanı veriyor. Aynı makine, aynı 600
saniye, aynı komut: yanıt hangi saniyede çalıştırıldığına bağlı. Bu, “sorunu görmek için ps
çalıştırdım, bir şey yoktu” cümlesinin ölçüsüdür.
Asıl sonuç son satırdadır. Ömür ortalaması, en kötü tek bakış kadar yanlış: 7 yanlış tanı. Ortalama almak sıçramayı yok etmiyor, seyreltiyor — beş saniyelik bir sıçrama 600 saniyeye bölündüğünde eşiğin çok altına iniyor. Daha uzun bir pencereye bakmak burada daha iyi bir tanı vermiyor; hangi ölçünün alındığı, ne kadar veri toplandığından önce gelir.
Ada Göre Aramanın Bedeli
Süreç aramanın iki yolu vardır. Listeyi metin olarak süzmek — ps çıktısını grep ile
daraltmak — aramayı yapan sürecin kendisini de yakalar ve kalıbı bozuk yazıldığında ilgisiz
satırları getirir. İkinci yol, süreç tablosunu doğrudan sorgulayan pgrep ve eşi pkill’dir:
$ pgrep -a -u uygulama kuyruk-isleyici 1128 /opt/kuyruk/kuyruk-isleyici --pay 3 1135 /opt/kuyruk/kuyruk-isleyici --pay 4
Bu döküm de örnektir ve çalıştırılmamıştır. pgrep metin süzmeye göre daha kesindir:
kendini listelemez, kullanıcıya ve oturuma göre daraltılabilir. Ama kesin olan şey
eşleşmedir, tanı değil. Ada göre seçmek, “bu adı taşıyan süreçler sorunludur” varsayımını
sessizce kabul eder.
# Onceki bloklarin uzerine: S ve GERCEK oradan gelir. ad_tablosu = {} for s in S: ad_tablosu.setdefault(s["komut"], [0, 0]) ad_tablosu[s["komut"]][0] += 1 ad_tablosu[s["komut"]][1] += 1 if s["pid"] in GERCEK else 0 print("komut adi eslesen gercekte agir ada gore yanlis dokunus") for k in sorted(ad_tablosu): toplam, agir = ad_tablosu[k] print(f" {k:20s} {toplam:7d} {agir:13d} {min(agir, toplam - agir):23d}") print("toplam yanlis dokunus (en iyi durumda):", sum(min(a, t - a) for t, a in ad_tablosu.values())) print("tek bir ada gore secim en cok kac agir sureci yakalar:", max(a for _, a in ad_tablosu.values()), "/", len(GERCEK))
komut adi eslesen gercekte agir ada gore yanlis dokunus kuyruk-isleyici 6 3 3 olcum-toplayici 5 2 2 onbellek-temizleyici 2 1 1 rapor-uretici 5 4 1 veri-alici 1 1 0 yedek-gorevi 5 3 2 toplam yanlis dokunus (en iyi durumda): 9 tek bir ada gore secim en cok kac agir sureci yakalar: 4 / 14
Hiçbir komut adı ağır süreçlerle örtüşmüyor. kuyruk-isleyici adını taşıyan altı süreçten
üçü ağır, üçü değil; adı seçen bir operatör ya üç masum süreci de kapsar ya da üç ağır süreci
dışarıda bırakır. En iyi durumda bile 9 sürece yanlış dokunulur, ve tek bir ad ağır
süreçlerin en çok 4’ünü yakalar — kâhin 14’tür.
Bunun nedeni kurgu değil, yapının kendisidir: komut adı bir kimlik değil, bir etikettir. Aynı program birden çok örnekle koşar, örneklerin yükü birbirinden bağımsızdır. Adla seçmek hızlıdır ve bu hız, dersin üçüncü dersinde sinyal gönderirken bedele dönüşür.
Özet
- Kursun ölçüsü üç sayıdır: kâhin, araç çıktısı ve yanlış tanı sayısı. Bir komutun değeri gösterdiği satır sayısı değil, o satırlardan çıkarılan tanının kaç kez yanlış olduğudur.
- Kurgu sunucudaki 24 sürecin 14’ü gerçekte ağırdır; bu kâhindir ve dersin bütün sayıları ona göre okunur.
- Örnekleme aralığı 15 saniyeye çıktığında araç 3, 30 ve 60 saniyede 5 ağır süreci kaçırır. Kaçanlar altmış saniyede bir sıçrayanlardır; araç baktığı anda haklıdır.
- Aralık 1 saniyede 14.400, 60 saniyede 240 satır üretir; ama 2.880 satır 14.400 satır kadar iyi tanı verir. Daha çok satır bir yerden sonra tanıya hiçbir şey katmaz.
- Tek bakış bakılan ana göre 5 ile 7 arasında yanlış tanı verir; sürecin doğumundan beri alınan ömür ortalaması 7 yanlış tanıyla en kötü tek bakış kadar kötüdür.
- Ada göre arama en iyi durumda 9 sürece yanlış dokunur ve tek bir ad ağır süreçlerin en çok 4’ünü yakalar; komut adı bir kimlik değil etikettir.
Sonraki Adım
Bu ders süreçlere dışarıdan baktı: liste, sütun, arama. Süreçlerin bir de operatörle kurdukları
bağ vardır — hangi terminale bağlılar, hangi oturuma aitler, oturum kapandığında ne olur.
Sonraki ders bu bağı ölçer: bir betik arka plana alındığında ve oturum kapatıldığında hangi
süreçlerin hayatta kaldığı, jobs çıktısının gösterdiğiyle hiç örtüşmeyebilir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.