Ders 10 / 22
Kod Yürütme Araçları
Ajanın yazdığı programı sanal alanda çalıştıran bir aracın kaynak sınırlarıyla ölçülmesi: aynı tutarı hesaplayan üç yazım biçimi 15, 172 ve 19 adım harcar, 2 ile 5 hücre tutar ve 1 ile 5 çıktı üretir. Gevşek sınırda hiçbir çağrı bildirilen sınırı aşmaz ama üç görev, çağrı başına sınır hiçbir şey durdurmadan 96 adımlık görev bütçesini geçer. Orta sınır 28 kod çağrısının 24'ünü durdurur ve durdurduğu sınıflar 20 adım ile 4 hücredir; sıkı sınırda aynı 24 çağrı bu kez 20 adım ve 4 çıktı sınıfından durur. Durdurma görevi doğrudan düşürmez, adım bütçesini tüketerek düşürür: kod görevlerinde başarım 0,7778'den 0,3333'e, ikinci koşumda 1,0000'den 0,5556'ya iner. Sıkı sınır orta sınırla aynı başarımı verirken boşa harcanan adımı 1356'dan 552'ye indirir. Koşan kod savunma tarafındadır.
İçindekiler
Önceki iki derste her araç sabit bir işi yapıp döndü, bu yüzden bir çağrının ne tutacağı sorulmadı. Ajanın kendi yazdığı bir programı çalıştıran araçta bu varsayım kalkar: aynı sonucu veren iki program yüz kat farklı kaynak harcayabilir ve bu fark tanımda yazmaz.
Ders böyle bir aracı sanal alan içinde kurar ve bir saldırı dersi değildir: hiçbir kaçış, atlatma ya da yetki yükseltme yordamı yazılmaz. Koşan kod bütünüyle savunma tarafındadır — sayar, sınırlar ve durdurur. Yetki sınırlandırma Linux ve Sistem Yönetimi ile Siber Güvenlik müfredatlarında en az yetki ilkesi olarak ölçüldü ve tekrarlanmaz; sayılan tek şey sınırın ne durdurduğu ve durdurmanın neye mal olduğudur.
- AB17. Ortam, araç kümesi, görev kümesi, kod yürütme aracı ve ajan döngüsü kurgudur; gerçek
bir çalışma zamanı, yürütme servisi ya da model uç noktası çağrılmaz. Tarife hesabı sabit bir
araç olmaktan çıkar;
tarifedüşer, yerinekod_yurutgelir ve araç kümesi yine beş kalır. Tohum 20260218, ikinci koşum 20260219. - AB18. Sanal alan küçük bir yazmaç makinesidir ve bildirilen üç kaynak sınırı taşır: adım, hücre, çıktı. Sınır aşıldığında çalışma durur ve aşılan sınıf bildirilir.
- AB19. Ajanın yazdığı program üç biçimden birindedir, biçim görev başına bir kez çekilir ve üç biçim de aynı tutarı hesaplar.
- AB20. Bir çağrının gerçek tüketimi kuru çalışmayla ölçülür: program sınırsıza yakın bir ayarla bir kez daha koşturulur, yalnız sayıma girer.
- AB21. Görev bütçesi 96 yürütme adımıdır ve görevin bütün kod çağrılarının toplamına bakar; sanal alan bunu görmez, çünkü sınırı çağrı başınadır.
- AB22. Taban çizgisi gevşek sınırdır, adım bütçesi sekizdir, kod görevi dizisinde
kod_yurutbulunandır: 24 görevin dokuzu.
Sanal Alan ve Üç Yazım Biçimi
Aşağıdaki kod ortak ortamı ve görev kümesini kurar, sonra yazmaç makinesini, bildirilen sınırları ve derleyiciyi ekler.
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_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}, "belge_ara": {"islev": t_belge, "alan": ("anahtar",), "yan_etki": False}, "kayit_yaz": {"islev": t_kayit, "alan": ("abone", "sutun", "deger"), "yan_etki": True}, } 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 # ---- KURGU kod yurutme araci: yazmac makinesi ve bildirilen kaynak siniri. # Kosan kod savunma tarafindadir: sayar , sinirlar , durdurur. SINIR = {"gevsek": {"adim": 512, "hucre": 16, "cikti": 16}, "orta": {"adim": 64, "hucre": 4, "cikti": 8}, "siki": {"adim": 24, "hucre": 4, "cikti": 2}} GOREV_BUTCE = 96 # gorev basina toplam yurutme adimi def deg(x, h): return h[x] if isinstance(x, str) else x def yurut(program, sinir): """Sinir asildiginda calisma durur ve asilan sinif bildirilir.""" hucre, cikti, ip, adim = {}, [], 0, 0 while ip < len(program): adim += 1 if adim > sinir["adim"]: return {"hata": "sinir asildi", "sinif": "adim", "harcanan": adim} k = program[ip] if k[0] == "ata": hucre[k[1]] = deg(k[2], hucre) elif k[0] == "topla": hucre[k[1]] += deg(k[2], hucre) elif k[0] == "carp": hucre[k[1]] *= deg(k[2], hucre) elif k[0] == "azalt": hucre[k[1]] -= 1 elif k[0] == "yaz": cikti.append(hucre[k[1]]) elif k[0] == "dallan" and hucre[k[1]] > 0: ip = k[2] continue if len(hucre) > sinir["hucre"]: return {"hata": "sinir asildi", "sinif": "hucre", "harcanan": adim} if len(cikti) > sinir["cikti"]: return {"hata": "sinir asildi", "sinif": "cikti", "harcanan": adim} ip += 1 return {"tutar": cikti[-1] if cikti else None, "harcanan": adim, "hucre": len(hucre), "cikti": len(cikti)} def derle(stil, m3, tip): """Ajanin yazdigi KURGU program; ucu de ayni tutari hesaplar.""" d, kalan, alt = [], m3, 0 for ust, birim in BASAMAK: # tarife basamaklarina ayir pay = min(kalan, ust - alt) if pay <= 0: break d.append((pay, birim)) kalan, alt = kalan - pay, ust if kalan > 0: d.append((kalan, USTU)) p = [("ata", "t", 0)] for i, (adet, birim) in enumerate(d): if stil == "kisa": p += [("ata", "x", adet), ("carp", "x", birim), ("topla", "t", "x")] elif stil == "birim": p += [("ata", "s", adet), ("topla", "t", birim), ("azalt", "s"), ("dallan", "s", len(p) + 1)] else: # acik yazim : basamak basina hucre ve cikti p += [("ata", f"d{i}", adet), ("carp", f"d{i}", birim), ("topla", "t", f"d{i}"), ("yaz", f"d{i}")] if tip == "isyeri": p.append(("carp", "t", ISYERI_KAT)) return p + [("yaz", "t")] AYAR = ["gevsek"] # sanal alanin bildirdigi sinir def t_kod(m3=None, tip="mesken", program=None, **_): if m3 is None or program is None: return {"hata": "eksik alan"} return yurut(program, SINIR[AYAR[0]]) # Tarife hesabi sabit bir arac degil , ajanin yazdigi bir programdir; arac sayisi bes kalir. ARAC["kod_yurut"] = {"islev": t_kod, "alan": ("m3", "tip", "program"), "yan_etki": False} ARAC_ADI = list(ARAC) for g in GOREV: g["dizi"] = tuple("kod_yurut" if a == "tarife" else a for a in g["dizi"]) STIL, STIL_PAY = ("kisa", "birim", "acik"), [0.40, 0.30, 0.30] for stil in STIL: p = derle(stil, 55, "isyeri") s = yurut(p, SINIR["gevsek"]) d = " ".join(f"{a} -> {yurut(p, SINIR[a]).get('sinif', 'tamam')}" for a in ("orta", "siki")) print(f"{stil:<6} komut {len(p):>2} adim {s['harcanan']:>3} hucre {s['hucre']}" f" cikti {s['cikti']} tutar {s['tutar']} | {d}")
kisa komut 15 adim 15 hucre 2 cikti 1 tutar 1100 | orta -> tamam siki -> tamam birim komut 19 adim 172 hucre 2 cikti 1 tutar 1100 | orta -> adim siki -> adim acik komut 19 adim 19 hucre 5 cikti 5 tutar 1100 | orta -> hucre siki -> cikti
Üç satır aynı tutarı, 1100’ü, üç ayrı kaynak profiliyle hesaplıyor. Komut sayıları neredeyse eşit — 15, 19, 19 — ve hiçbir sınır bu sayıdan okunamaz. Birim birim toplayan biçim 172 adım harcar, çünkü komutlarının dördü bir geri dallanmadır; açık yazım biçimi on dokuz adımda biter ama beş hücre açar ve beş çıktı üretir. Kaynak sınırı bu yüzden tekil değildir: ikinci biçimi adım sınırı, üçüncüsünü orta ayarda hücre, sıkı ayarda çıktı sınırı durdurur.
Sınırın Durdurduğu ve Durduramadığı
Aynı 24 görev üç sınır ayarında ve iki tohumda koşturulur; sınırı aşan çağrı kuru çalışmayla saptanır, etkin sınır ise gerçekten durdurur.
def ajan_kod(g, en_cok_adim=8, tohum=TOHUM): """Ortak ajan dongusu; tek fark tarife yerine ajanin yazdigi programin sanal alanda yurutulmesi ve her yurutmenin kaydedilmesi.""" r = uretec(tohum ^ izno(g["ad"])) stil = STIL[ayrik(r(), STIL_PAY)] # gorev basina tek yazim bicimi alan = {"abone": g["abone"], "anahtar": g["istek"], "sutun": "bedel"} kod_iz, adim, dizi, k = [], 0, g["dizi"], 0 while adim < en_cok_adim: adim += 1 hedef = dizi[k] if k < len(dizi) else None if hedef is None: if r() < 0.88: break 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 sec == "kayit_yaz": alan["deger"] = alan.get("sonuc") prog = None if sec == "kod_yurut" and "m3" in alan: prog = alan["program"] = derle(stil, alan["m3"], alan.get("tip", "mesken")) s = cagir_arac(sec, alan) if prog is not None: kod_iz.append((prog, s)) if "hata" in s: continue alan.update({kk: vv for kk, vv in s.items() if kk != "hata"}) if sec == "tuketim": alan["sonuc"] = s["m3"] if sec == "kod_yurut": alan["sonuc"] = s["tutar"] if sec == "belge_ara": alan["sonuc"] = s["kod"] if sec == hedef: k += 1 return {"adim": adim, "kod_iz": kod_iz, "yanit": alan.get("sonuc")} def olc(ayar, tohum=TOHUM): """Sinir denetimi: kuru calisma gercek tuketimi verir , etkin sinir durdurur.""" AYAR[0], lim, sinif = ayar, SINIR[ayar], {} ok = kod = asan = durdurulan = bosa = butce = ok_kod = n_kod = 0 for g in GOREV: s = ajan_kod(g, tohum=tohum) d = s["yanit"] == dogru_yanit(g) ok += d if "kod_yurut" in g["dizi"]: n_kod, ok_kod = n_kod + 1, ok_kod + d toplam = 0 for prog, sonuc in s["kod_iz"]: kuru = yurut(prog, SINIR["gevsek"]) # yalniz sayim icin kod += 1 asan += (kuru["harcanan"] > lim["adim"] or kuru["hucre"] > lim["hucre"] or kuru["cikti"] > lim["cikti"]) toplam += sonuc["harcanan"] if "hata" in sonuc: durdurulan += 1 bosa += sonuc["harcanan"] sinif[sonuc["sinif"]] = sinif.get(sonuc["sinif"], 0) + 1 butce += toplam > GOREV_BUTCE return kod, asan, durdurulan, bosa, butce, ok / len(GOREV), ok_kod / n_kod, sinif print("sinir kod cagrisi asan durdurulan bosa adim butceyi asan" " basarim kod gorevi") for ayar in SINIR: for tohum, e in ((TOHUM, "A"), (TOHUM + 1, "B")): a = olc(ayar, tohum) print(f"{ayar:<7}{e} {a[0]:>10} {a[1]:>5} {a[2]:>11} {a[3]:>10} {a[4]:>13}" f" {a[5]:>7.4f} {a[6]:>10.4f}") for ayar in ("orta", "siki"): print(f" {ayar:<5} durdurma siniflari :", olc(ayar)[7])
sinir kod cagrisi asan durdurulan bosa adim butceyi asan basarim kod gorevi
gevsek A 9 0 0 0 3 0.8750 0.7778
gevsek B 10 0 0 0 1 1.0000 1.0000
orta A 28 24 24 1356 4 0.7083 0.3333
orta B 22 17 17 646 2 0.8333 0.5556
siki A 28 24 24 552 4 0.7083 0.3333
siki B 22 17 17 317 1 0.8333 0.5556
orta durdurma siniflari : {'adim': 20, 'hucre': 4}
siki durdurma siniflari : {'adim': 20, 'cikti': 4}
İkinci ve üçüncü sütun her satırda eşittir: bildirilen sınırı aşan çağrı sayısı ile durdurulan çağrı sayısı aynıdır. Çağrı başına konan bir sınır, çağrı başına her ihlali yakalar; bu bir başarı değil, tanımın gereğidir. Sayılmaya değer olan, sınırın görmediği yerdir.
Görmediği yer beşinci sütundadır. Gevşek ayarda hiçbir çağrı durdurulmaz, ama üç görev 96 adımlık bütçeyi geçer; çağrı başına 512 adıma izin veren bir sınır, 172 adımlık bir programın kaç kez çalıştırıldığını saymaz. Orta ve sıkı ayarda durdurulan çağrılar tekrarlandığı için bütçeyi aşan görev dörde çıkar. İkisi aynı şeyi söyler: çağrı başına sınır görev toplamını görmez.
Durdurmanın bedeli son sütundadır. Gevşek ayarda kod görevlerinde başarım 0,7778 ve 1,0000, orta ayarda 0,3333 ve 0,5556. Düşüş iki koşumda da 0,4445’e yakındır ve gevşek ayardaki iki koşum farkının (0,2222) iki katıdır, yani ölçülmüştür. Mekanizma dolaylıdır: durdurulan bir çağrı görevi düşürmez, adım bütçesini tüketir. Yazım biçimi görev başına sabit olduğu için aynı program yeniden yazılır ve bütçe biter; kod çağrısının 9’dan 28’e çıkması budur.
Orta ile sıkı satırlarını ayıran tek sütun boşa harcanan adımdır: 1356’ya karşı 552. Durdurulan çağrı ve başarım aynıyken sıkı sınır atılan işin üçte ikisini geri kazanıyor; kazanç isabette değil kaynaktadır.
Özet
- Aynı tutarı veren üç program 15, 172 ve 19 adım harcar, 2 ile 5 hücre tutar, 1 ile 5 çıktı üretir; kaynak sınırı bu yüzden tekil değil çoğuldur.
- Her satırda aşan çağrı sayısı durdurulan çağrı sayısına eşittir: çağrı başına sınır, çağrı başına her ihlali yakalar. Görmediği yer görev toplamıdır: gevşek ayarda hiçbir çağrı durdurulmadan üç görev 96 adımlık bütçeyi aşar, sınırlı ayarlarda dört görev aşar.
- Durdurma görevi doğrudan düşürmez, adım bütçesini tüketerek düşürür: kod görevlerinde başarım 0,7778 ve 1,0000’den 0,3333 ve 0,5556’ya iner, kod çağrısı 9’dan 28’e çıkar. Sıkı sınır orta sınırla aynı başarımı verir ve boşa harcanan adımı 1356’dan 552’ye indirir.
Sonraki Adım
Burada sınırlanan şey tüketimdi: bir çağrının kaç adım süreceği, kaç hücre tutacağı, kaç çıktı üreteceği. Kaynak sınırı bir dördüncü soruya hiç dokunmaz: aracın neye erişebildiğine. Sanal alandaki programın dışarısı yoktu; ajanın dokunduğu öbür yüzeyler böyle değildir. Bir dosya ağacı ya da bir kabuk, yürütmeyi hiç uzatmadan geri alınamaz bir iş yapabilir. Sonraki ders aracın bildirdiği yetki yüzeyini sayar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.