Ders 11 / 22
Dosya Sistemi ve Terminal Erişimi
Ajanın dosya ve komut yüzeyinde yetki sınırlandırmasının sayılması: yirmi dört kurgu yüzey görevi üç yetki kümesinde koşturulur ve tamamlanan görev ile durdurulan çağrı yan yana basılır. Tam yetkide 0,9583 görev tamamlanıyor ve kapı hiçbir çağrıyı durdurmuyor; salt okuma yetkisi 71 çağrı durduruyor ama tamamlanan görevi 0,5000'e düşürüyor; izin listeli küme 20 çağrı durdurup 0,8333'te kalıyor ve durdurmalarının tamamı tek bir görev türünde toplanıyor. Salt okumada doğru yanıt 0,6250 iken tamamlanan görev 0,5000'dir: üç görevde yanıt doğru üretildi ama yazma hiç gerçekleşmedi. Durdurulan çağrı adımı da tüketir; adım 78'den 129'a çıkar. İki koşumda toplamlar aynı kalsa da görev düzeyinde iki görev yer değiştirir, bu yüzden ölçüm bandı 0,0833'tür ve tam yetki ile izin listesi arasındaki 0,1250 fark bandın üstündedir.
İçindekiler
Bir önceki ders kod yürütme aracını bir kaynak sınırına bağladı ve sınırın kaç çağrıyı durdurduğunu saydı. Orada durduran şey miktardı: bellek, süre, çıktı uzunluğu. Ajanın dokunduğu yüzey ise bununla bitmiyor: aynı döngü dosya okur, dosya yazar ve işletim komutu çalıştırır. Bu üç eylemde durduran şey miktar değil yetkidir.
Ders o yetkiyi tek kavramda toplar: yetki yüzeyi (permission surface), bir aracın bildirdiği yetenek ile dokunduğu yol ya da komuttur. En az yetki ilkesi Siber Güvenliğe Giriş kursunda kuruldu, dosya izinleri ve sahiplik Linux’a Giriş kursunda ölçüldü; iki yordam da tekrarlanmaz. Sayılan tek şey şudur: üç yetki kümesinde ajan kaç görevi bitiriyor, kapı kaç çağrıyı durduruyor ve durdurma kime fatura ediliyor.
- AB31. Kod bir benzeticidir; gerçek bir dosya sistemi ya da çalışma zamanı çağrılmaz. Ortam, araçlar ve görevler kurgudur, tohum 20260218.
- AB32. Ajan döngüsü kursun ortak tanımıdır: doğru aracı seçme payı derinlikle düşer, iş bitince ajan 0,88 payla durur.
- AB33. Yetki yüzeyi aracın bildirdiği alandır: her araç bir yetenek (okuma, yazma, çalıştırma) bildirir; dokunduğu yol ya da komut çağrının içinden okunur. Kurgu ağaç beş yol, kurgu terminal yüzeyi dört komut taşır.
- AB34. Kapı yürütücünün önünde durur. Geçmeyen çağrı araca ulaşmaz, döngüye araç hatası olarak döner ve adımı tüketir. Ölçülen üç küme tam, salt okuma, izin listeli.
- AB35. Görev tamamlandı demek için iki koşul aranır: yanıt doğru olmalı ve dizinin yan etkili adımı yürümüş olmalı. Yalnız yanıta bakmak yazmayan bir görevi bitmiş sayar.
- AB36. Taban çizgisi tam yetki kümesidir — kapının hiçbir şeyi durdurmadığı döngü. Bedel durdurulan çağrı, adım ve düşen görev.
Ortak Döngü ve Yüzeyin Bildirimi
Ortam, beş temel araç ve ajan döngüsü kurs boyunca aynıdır.
TOHUM, M32 = 20260218, 0xFFFFFFFF def uretec(t): x = ((t ^ (t >> 16)) * 2246822507) & M32 x = ((x ^ (x >> 13)) * 3266489909) & M32 s = [(x ^ (x >> 16)) & M32] def sonraki(): s[0] = (s[0] * 1664525 + 1013904223) & M32 return s[0] / 4294967296 return sonraki def ayrik(u, w): t = 0.0 for i, x in enumerate(w): t += x if u < t: return i return len(w) - 1 def belirtecle(m): b = [] for s in str(m).lower().replace(",", " , ").split(): while len(s) > 5: b.append(s[:5]) s = s[5:] b.append(s) return b def izno(m): h = 2166136261 for c in str(m): h = ((h ^ ord(c)) * 16777619) & M32 return h # ---- KURGU ortam: olcum aginin kayitlari BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"] TIP = ["mesken", "isyeri"] ABONE = {} for i in range(60): r = uretec(TOHUM + 31 * i) onceki = 10000 + int(r() * 80000) ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)], "onceki": onceki, "simdiki": onceki + int(r() * 70)} BASAMAK, USTU = ((10, 4), (25, 7), (40, 11)), 16 ISYERI_KAT = 2 BELGE = {"TR01": "tarife basamaklari 10 25 40 metrekup ve ustu", "TR02": "isyeri abonesinde birim ucret iki katidir", "SY01": "endeks farki tuketimi verir sayac donusu 100000 eklenir", "AR01": "ariza kaydi acildiginda saha ekibi iki gun icinde gider", "KS01": "planli kesinti duyurusu bir hafta once yayimlanir"} CAGRI = [0] # arac cagri sayaci def _bedel(m3, tip): kalan, alt, top = m3, 0, 0 for ust, birim in BASAMAK: dilim = min(kalan, ust - alt) if dilim <= 0: break top += dilim * birim kalan -= dilim alt = ust top += kalan * USTU return top * (ISYERI_KAT if tip == "isyeri" else 1) def t_sayac_oku(abone=None, **_): a = ABONE.get(abone) if a is None: return {"hata": "abone yok"} return {"onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"], "bolge": a["bolge"]} def t_tuketim(onceki=None, simdiki=None, **_): if onceki is None or simdiki is None: return {"hata": "eksik alan"} f = simdiki - onceki return {"m3": f + 100000 if f < 0 else f} def t_tarife(m3=None, tip="mesken", **_): if m3 is None: return {"hata": "eksik alan"} return {"tutar": _bedel(m3, tip)} def t_belge(anahtar=None, **_): if not anahtar: return {"hata": "eksik alan"} ab = set(belirtecle(anahtar)) en, kod = -1, None for k, m in BELGE.items(): o = len(ab & set(belirtecle(m))) if o > en: en, kod = o, k return {"kod": kod, "metin": BELGE[kod]} if en > 0 else {"hata": "bulunamadi"} def t_kayit(abone=None, sutun=None, deger=None, **_): if not (abone and sutun and deger is not None): return {"hata": "eksik alan"} return {"yazildi": True, "abone": abone, "sutun": sutun, "deger": deger} ARAC = { "sayac_oku": {"islev": t_sayac_oku, "alan": ("abone",), "yan_etki": False}, "tuketim": {"islev": t_tuketim, "alan": ("onceki", "simdiki"), "yan_etki": False}, "tarife": {"islev": t_tarife, "alan": ("m3", "tip"), "yan_etki": False}, "belge_ara": {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False}, "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True}, } ARAC_ADI = list(ARAC) def cagir_arac(ad, durum): """Sema disindaki alanlar suzulur; eksik alan aracin kendi hatasidir.""" CAGRI[0] += 1 if ad not in ARAC: return {"hata": "arac yok"} kw = {a: durum[a] for a in ARAC[ad]["alan"] if a in durum} return ARAC[ad]["islev"](**kw) # ---- KURGU gorevler: her biri bilinen bir arac dizisiyle cozulur GOREV = [] for i in range(24): r = uretec(TOHUM + 9973 * i) ab = f"A{1 + int(r() * 60):03d}" t = ayrik(r(), [0.30, 0.22, 0.20, 0.28]) if t == 0: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "bedel", "abone": ab, "istek": f"{ab} abonesinin bu donem bedeli nedir", "dizi": ("sayac_oku", "tuketim", "tarife")}) elif t == 1: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "tuketim", "abone": ab, "istek": f"{ab} abonesinin bu donem tuketimi kac metrekup", "dizi": ("sayac_oku", "tuketim")}) elif t == 2: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "belge", "abone": ab, "istek": "sayac donusunde endeks farki nasil hesaplanir", "dizi": ("belge_ara",)}) else: GOREV.append({"ad": f"G{i + 1:02d}", "tur": "kayit", "abone": ab, "istek": f"{ab} abonesinin bedelini hesapla ve kayda yaz", "dizi": ("sayac_oku", "tuketim", "tarife", "kayit_yaz")}) def dogru_yanit(g): a = ABONE[g["abone"]] f = a["simdiki"] - a["onceki"] m3 = f + 100000 if f < 0 else f if g["tur"] == "tuketim": return m3 if g["tur"] == "belge": return "SY01" return _bedel(m3, a["tip"]) # ---- KURGU ajan: her adimda bir arac secer ya da biter def gorme(d): return max(0.34, 0.80 - 0.09 * (d - 1)) # dogru araci secme payi, derinlikle duser def ajan(g, en_cok_adim=8, tohum=TOHUM, oz_elestiri=False, onay=False): """KURGU ajan dongusu. Gercek bir model cagrilmaz; arac secimi gorevin dizisine ve derinlige bagli tek bir cekilisten gelir.""" r = uretec(tohum ^ izno(g["ad"])) alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} iz, adim, bel, hata = [], 0, 0, 0 dizi, k = g["dizi"], 0 while adim < en_cok_adim: adim += 1 bel += 60 + 22 * len(iz) hedef = dizi[k] if k < len(dizi) else None if hedef is None: # is bitti , ajan durmali if r() < 0.88: return {"bitti": True, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} sec = ARAC_ADI[int(r() * len(ARAC_ADI))] else: sec = hedef if r() < gorme(k + 1) else ARAC_ADI[int(r() * len(ARAC_ADI))] if ARAC[sec]["yan_etki"] and onay: alan["onay"] = alan.get("onay", 0) + 1 if sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") s = cagir_arac(sec, alan) iz.append((sec, "hata" in s)) bel += 30 if "hata" in s: hata += 1 if oz_elestiri: bel += 40 continue alan.update({kk: vv for kk, vv in s.items() if kk != "hata"}) if sec == "tuketim": alan["sonuc"] = s["m3"] if sec == "tarife": alan["sonuc"] = s["tutar"] if sec == "belge_ara": alan["sonuc"] = s["kod"] if sec == hedef: k += 1 return {"bitti": False, "adim": adim, "iz": iz, "belirtec": bel, "hata": hata, "yanit": alan.get("sonuc"), "onay": alan.get("onay", 0)} print("ortak ortam:", len(ABONE), "abone ,", len(BELGE), "belge ,", len(ARAC), "arac ,", len(GOREV), "gorev")
ortak ortam: 60 abone , 5 belge , 5 arac , 24 gorev
Üç Yetki Kümesi ve Kapı
Yüzey üç araçla açılır: dosya_oku, dosya_yaz, komut_calistir; ortak kümedeki kayit_yaz da
yazma yeteneği bildirir. Kapı bu bildirimi yetki kümesiyle karşılaştırır ve yalnız durdurur;
kodun hiçbir yerinde sınırı aşan bir yol yoktur, koşan her satır denetim tarafındadır. Yirmi dört
kurgu yüzey görevi altı türe dağılır, üçü yan etki taşır.
# ---- KURGU dosya agaci ve terminal yuzeyi (bu derse ozgu) AGAC = {"veri/endeks.csv": 60, "veri/sonuc.csv": 0, "belge/tarife.txt": 5, "ayar/esik.cfg": 2, "gunluk/istek.log": 41} KOMUT = {"endeks_dokum": 60, "gunluk_kuyruk": 12, "arsiv_temizle": 7, "sayac_sifirla": 0} YOL_IZ = {"endek": "veri/endeks.csv", "sonuc": "veri/sonuc.csv", "tarif": "belge/tarife.txt", "esik": "ayar/esik.cfg", "gunlu": "gunluk/istek.log"} KOMUT_IZ = {"dokum": "endeks_dokum", "kuyru": "gunluk_kuyruk", "temiz": "arsiv_temizle", "sifir": "sayac_sifirla"} def yol_coz(a, kip): """Okuma ilk, yazma son eslesmeyi alir.""" e = [YOL_IZ[t] for t in belirtecle(a) if t in YOL_IZ] return (e[0] if kip == "oku" else e[-1]) if e else "gunluk/istek.log" def komut_coz(a): return next((KOMUT_IZ[t] for t in belirtecle(a) if t in KOMUT_IZ), None) def t_dosya_oku(anahtar="", abone=None, **_): yol = yol_coz(anahtar, "oku") if yol == "veri/endeks.csv": a = ABONE.get(abone) return {"hata": "eksik alan"} if a is None else { "onceki": a["onceki"], "simdiki": a["simdiki"], "tip": a["tip"]} if yol == "belge/tarife.txt": return {"sonuc": "TR01"} return {"sonuc": USTU if yol == "ayar/esik.cfg" else AGAC[yol]} def t_dosya_yaz(anahtar="", sonuc=None, **_): return {"hata": "eksik alan"} if sonuc is None else {"yazildi": yol_coz(anahtar, "yaz")} def t_komut(anahtar="", **_): k = komut_coz(anahtar) return {"hata": "komut yok"} if k is None else {"sonuc": KOMUT[k]} ARAC.update({"dosya_oku": {"islev": t_dosya_oku, "alan": ("anahtar", "abone"), "yan_etki": False}, "dosya_yaz": {"islev": t_dosya_yaz, "alan": ("anahtar", "sonuc"), "yan_etki": True}, "komut_calistir": {"islev": t_komut, "alan": ("anahtar",), "yan_etki": True}}) ARAC_ADI = list(ARAC) YETENEK = {"dosya_oku": "oku", "dosya_yaz": "yaz", "kayit_yaz": "yaz", "komut_calistir": "calistir"} YETKI = {"tam": {"oku": ("",), "yaz": ("",), "komut": None}, "salt okuma": {"oku": ("",), "yaz": (), "komut": ()}, "izin listeli": {"oku": ("veri/", "belge/", "ayar/"), "yaz": ("veri/sonuc",), "komut": ("endeks_dokum", "gunluk_kuyruk")}} def izin_ver(ad, durum, y): """Aracin bildirdigi yuzeyi verilen yetki kumesiyle karsilastirir.""" g = YETENEK.get(ad) if g is None: return True if g == "calistir": return y["komut"] is None or komut_coz(durum.get("anahtar", "")) in y["komut"] if ad == "kayit_yaz": return bool(y[g]) return any(yol_coz(durum.get("anahtar", ""), g).startswith(o) for o in y[g]) AKTIF, DUR = [YETKI["tam"]], {"sayi": 0} _yurut = cagir_arac def cagir_arac(ad, durum): """Kapi yurutucunun onundedir; gecmeyen cagri araca ulasmaz.""" if izin_ver(ad, durum, AKTIF[0]): return _yurut(ad, durum) DUR["sayi"] += 1 return {"hata": "yetki yok"} # ---- KURGU yuzey gorevleri: 24 gorev, alti tur TUR = [("endeks", "{a} abonesinin endeks satirini oku ve tuketimi hesapla", ("dosya_oku", "tuketim")), ("belge", "tarife basamaklarini belgeden oku", ("dosya_oku",)), ("esik", "ustu birim ucret esik degerini ayardan oku", ("dosya_oku",)), ("yazma", "{a} abonesinin endeks farkini hesapla ve sonuc dosyasina yaz", ("dosya_oku", "tuketim", "dosya_yaz")), ("dokum", "endeks dokumunu calistir", ("komut_calistir",)), ("temizlik", "arsiv temizligini calistir", ("komut_calistir",))] YUZEY = [] for i in range(24): r = uretec(TOHUM + 6421 * i) ab = f"A{1 + int(r() * 60):03d}" ad, metin, dizi = TUR[ayrik(r(), [0.20, 0.12, 0.14, 0.18, 0.18, 0.18])] YUZEY.append({"ad": f"Y{i + 1:02d}", "tur": ad, "abone": ab, "istek": metin.format(a=ab), "dizi": dizi}) def yuzey_dogru(g): a = ABONE[g["abone"]] return {"endeks": a["simdiki"] - a["onceki"], "yazma": a["simdiki"] - a["onceki"], "belge": "TR01", "esik": USTU, "dokum": KOMUT["endeks_dokum"], "temizlik": KOMUT["arsiv_temizle"]}[g["tur"]] def kosum(yetki, tohum=TOHUM): """Gorev bitti demek icin yanit dogru olmali ve yan etkili adim yurumus olmali.""" AKTIF[0] = YETKI[yetki] CAGRI[0] = DUR["sayi"] = 0 c = {"dogru": [], "bitti": [], "adim": 0, "pay": {}} for g in YUZEY: onceki = DUR["sayi"] s = ajan(g, tohum=tohum) d = s["yanit"] == yuzey_dogru(g) c["dogru"].append(d) c["bitti"].append(d and all(any(x == t and not h for x, h in s["iz"]) for t in g["dizi"] if ARAC[t]["yan_etki"])) c["adim"] += s["adim"] c["pay"][g["tur"]] = c["pay"].get(g["tur"], 0) + DUR["sayi"] - onceki c.update(cagri=CAGRI[0], dur=DUR["sayi"]) return c print("yuzey gorev turleri:", {t[0]: sum(g["tur"] == t[0] for g in YUZEY) for t in TUR}) print("yetki kumesi dogru A dogru B tamamlanan yurutulen durdurulan adim oynak") tablo = {} for y in YETKI: a, b = kosum(y), kosum(y, TOHUM + 1) tablo[y] = a print(f"{y:<14} {sum(a['dogru']) / 24:>7.4f} {sum(b['dogru']) / 24:>7.4f}" f" {sum(a['bitti']) / 24:>10.4f} {a['cagri']:>9} {a['dur']:>10}" f" {a['adim']:>4} {sum(x != z for x, z in zip(a['bitti'], b['bitti'])):>5}") print("\ndurdurulan cagrinin gorev turune dagilimi") for y in ("salt okuma", "izin listeli"): print(f" {y:<13}", {k: v for k, v in tablo[y]["pay"].items() if v})
yuzey gorev turleri: {'endeks': 6, 'belge': 3, 'esik': 3, 'yazma': 5, 'dokum': 4, 'temizlik': 3}
yetki kumesi dogru A dogru B tamamlanan yurutulen durdurulan adim oynak
tam 0.9583 0.9583 0.9583 54 0 78 2
salt okuma 0.6250 0.6250 0.5000 46 71 129 0
izin listeli 0.8333 0.8333 0.8333 51 20 92 2
durdurulan cagrinin gorev turune dagilimi
salt okuma {'yazma': 22, 'temizlik': 19, 'dokum': 30}
izin listeli {'temizlik': 20}
Durdurmanın Kime Fatura Edildiği
Taban çizgisi ilk satırdır: kapı hiçbir çağrıyı durdurmuyor, görevlerin 0,9583’ü bitiyor. Yetkiyi okumaya indirmek durdurulanı 71’e çıkarıyor ama tamamlananı 0,5000’e düşürüyor; izin listesi 20 çağrı durdurup 0,8333’te kalıyor.
Asıl bilgi son iki satırdadır. Salt okumanın 71 durdurması üç türe yayılıyor: yazma 22,
dokum 30, temizlik 19. İzin listesinin 20 durdurmasının ise tamamı temizlik türündedir.
En az yetki ilkesinin ölçülmüş hâli budur: yetkiyi yeteneğe göre kesmek üç görev türünü birden
düşürürken, izin listesi maliyetin tamamını kapatmak istediği türe yıkıyor. Tam yetkiden farkı
yalnız 0,1250, yani üç temizlik görevidir.
Bu farkın ölçülüp ölçülmediğini son sütun söyler. İki koşumun toplamları üç satırda da aynı, ama toplamın sabit olması koşum değişkenliğinin sıfır olduğu anlamına gelmez: oynak sütunu tam yetkide ve izin listesinde ikişer görevin sonucunu değiştirdiğini, birbirlerini götürdükleri için toplamın oynamadığını söylüyor. Ölçüm bandı ’tür; 0,1250 bandın üstündedir ve ölçülmüştür, salt okumanın 0,4583’lük düşüşü fazlasıyla üstündedir.
Geriye iki okuma kalıyor. Doğru yanıt ile tamamlanan görev salt okumada ayrışıyor: 0,6250 doğru, 0,5000 tamamlanmış. Aradaki üç görevde ajan doğru sayıyı üretti ama yazma çağrısı kapıda durduruldu; yalnız yanıta bakan bir ölçüt üçünü de bitmiş sayardı. Adım sütunu durdurmanın ücretsiz olmadığını söylüyor: kapıdan dönen hata döngüye araç hatası gibi görünür, ajan adımı yeniden dener. Salt okuma 78 yerine 129 adım, yani %65 fazla harcayıp daha az iş bitiriyor.
Özet
- Yetki yüzeyi, bir aracın bildirdiği yetenek ile dokunduğu yol ya da komuttur; kapı bu bildirimi yetki kümesiyle karşılaştırır ve yalnız durdurur.
- Tam yetkide 24 görevin 0,9583’ü bitiyor ve hiçbir çağrı durmuyor; salt okuma 71 çağrı durdurup tamamlananı 0,5000’e indiriyor; izin listesi 20 durdurup 0,8333’te kalıyor.
- İzin listesinin 20 durdurmasının tamamı tek görev türünde, salt okumanınki üç türe yayılıyor; en az yetki ilkesinin ölçülebilir farkı budur.
- Doğru yanıt tamamlanmış görev demek değildir: salt okumada üç görevde yanıt doğruydu ama yazma durduruldu, ölçüt 0,6250 yerine 0,5000 okur.
- Durdurma bedava değildir: salt okuma 129 adımla tam yetkinin 78 adımından %65 fazla harcar; iki koşumda ikişer görev yer değiştirdiği için ölçüm bandı 0,0833’tür.
Sonraki Adım
Bu derste ajanın dokunduğu her yüzey bizimdi: dosya ağacı da, komut kümesi de, kapı da ölçüm ağının içindeydi. Bir çağrıyı durdurabilmek, kimin neye yetkili olduğunu bildiğimiz için mümkündü. Ajan dışarıdan bilgi getirdiğinde bu zemin kayar: getirilen metin bizim değildir, bir izin kümesiyle denetlenemez ve duruma girdikten sonra bütün adımlara taşınır. Sonraki ders dış bilgiyi bir kaynak sınıflandırması olarak ele alır ve iki şeyi sayar: sınıf karışımı doğru yanıt payını nasıl değiştiriyor, ve yanlış bir kaynak kaç adım taşınıyor.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.