- Linux'un süreç bellek yapısını gerçek çalışma düzeyinde açıklıyor; sanal adres alanı ile fiziksel bellek arasındaki ilişkiyi adım adım ele alıyor
- Page table, VMA, mmap, page fault, CoW gibi temel mekanizmalara odaklanarak süreçlerin belleği nasıl sahiplendiğini ve ona nasıl eriştiğini somut biçimde anlatıyor
/proc dosya sistemi üzerinden süreç bazlı bellek durumunun nasıl gözlemleneceğini ve pagemap, kpageflags gibi gelişmiş tanılama araçlarının rolünü tanıtıyor
- Transparent Huge Pages (THP), userfaultfd, PAGEMAP_SCAN gibi modern çekirdek özellikleriyle performans optimizasyonu ve kullanıcı alanı dirty tracking tekniklerini ele alıyor
- Meltdown için PTI, TLB flush, W^X politikası gibi güvenlik ve performans odaklı çekirdek tasarım ilkelerini de açıklayarak Linux bellek yönetimine bütüncül bir anlayış sunuyor
Süreç belleğinin temel yapısı
- Bir program çalıştığında devasa ve kesintisiz bir bellek varmış gibi görünür; ancak gerçekte bunu Linux çekirdeği sayfa düzeyinde dinamik olarak oluşturur
- CPU, sanal adresi fiziksel çerçeveye çevirmek için page table'ı sorgular
- Eşleme yoksa page fault oluşur; çekirdek yeni bir sayfa ayırır ya da hata döndürür
- Fiziksel RAM yetersiz kaldığında çekirdek kullanılmayan sayfaları diske taşır veya dosya sayfalarını çıkararak alan açar
/proc, çekirdeğin bellekte oluşturduğu sanal dosya sistemidir ve süreç ile çekirdek durumunu dosya biçiminde dışarı sunar
Adres alanı ve VMA
- Her süreç tek bir adres alanı nesnesine sahiptir; bunun içi birden fazla VMA (Virtual Memory Area) ile oluşturulur
- VMA, aynı izinlere (R/W/X) ve aynı arka uca (anonim bellek veya dosya) sahip kesintisiz adres aralığıdır
- Page table, donanımın başvurduğu yapıdır ve sanal sayfalar ile fiziksel sayfalar arasındaki eşleme bilgisini (PTE) saklar
- Adres alanı değişiklikleri üç sistem çağrısıyla yapılır
mmap: yeni alan oluşturma
mprotect: izin değiştirme
munmap: eşlemeyi kaldırma
- Sayfalar varsayılan olarak 4KiB boyutundadır; bazı sistemler 2MiB ve 1GiB büyük sayfaları da destekler
/proc/self/maps ile bellek yapısını görmek
cat /proc/self/maps komutuyla sürecin bellek eşlemesi görülebilir
- Çalıştırılabilir dosyanın kodu, verisi, bss bölümü, heap, anonim eşlemeler, paylaşımlı kütüphaneler ve stack gösterilir
[vdso] ve [vvar] alanları, çekirdeğin eşlediği hızlı sistem çağrıları için kod ve veri bölgeleridir
mmap nasıl çalışır
mmap, gerçek bir bellek ayırma işlemi değil; adres alanı üzerinde bir taahhüt kaydı oluşturur
- Sayfalar ilk erişim anında ayrılır
- Dosya eşlemelerinde
offset sayfa hizalı olmalıdır; dosya sonunun ötesine erişim SIGBUS üretir
MAP_SHARED değişiklikleri doğrudan dosyaya yansıtır, MAP_PRIVATE ise write sırasında copy-on-write (CoW) ile bağımsız sayfa oluşturur
MAP_FIXED_NOREPLACE, belirtilen adreste zaten bir eşleme varsa işlemi başarısız kılarak güvenliği artırır
İlk erişim ve page fault
- Yeni bir eşlemeye ilk erişimde CPU page table'da karşılık bulamazsa page fault oluşur
- Çekirdek adresin geçerliliğini, erişim iznini ve varlığını denetler
- Anonim eşlemeyse sıfırlarla doldurulmuş yeni sayfa ayırır; dosya eşlemeyse page cache'den okur
- minor fault, veri zaten RAM'deyse; major fault ise disk I/O gerektiğinde oluşur
- Stack, guard page ile korunur; fazla aşağıya erişimde
SIGSEGV oluşur
fork() ve MAP_PRIVATE için Copy-on-Write
fork sırasında ebeveyn ve çocuk süreç aynı fiziksel sayfaları paylaşır ve bunların tümü salt okunur işaretlenir
- Yalnızca yazma anında yeni sayfa kopyalanır ve bağımsızlık korunur
MAP_PRIVATE dosya eşlemeleri de aynı ilkeyle çalışır
- İlgili seçenekler
vfork: ebeveynin adres alanını paylaşır
clone(CLONE_VM): thread oluşturur
MADV_DONTFORK, MADV_WIPEONFORK: eşlemeyi çocuk süreçten hariç tutar veya sıfırlayarak başlatır
İzin değiştirme ve TLB geçersiz kılma
mprotect ile sayfa izinleri değiştirildiğinde çekirdek VMA bölme ve page table güncelleme yapar, ardından TLB geçersiz kılma uygular
- W^X politikası gereği bir sayfa aynı anda hem yazılabilir hem çalıştırılabilir olamaz
- TLB (Translation Lookaside Buffer), son adres çevirilerinin önbelleğidir; geçersiz kılma kısa gecikme yaratabilir
/proc üzerinden ayrıntılı gözlem
/proc/<pid>/maps, smaps, smaps_rollup ile alan bazında izinler, RSS ve HugePage kullanımı görülebilir
/proc/<pid>/pagemap, sayfa düzeyinde durum bilgisi sunar (mevcut, swap'te, PFN vb.); ancak PFN normal kullanıcılara kapalıdır
/proc/kpagecount, /proc/kpageflags, PFN başına eşleme sayısını ve sayfa özelliklerini (anonim, dosya, dirty vb.) gösterir
mincore, SEEK_DATA/SEEK_HOLE ile seyrek dosyalardaki veri ve boşluk bölgeleri saptanabilir
PAGEMAP_SCAN ile userfaultfd birlikte kullanılarak kullanıcı alanı dirty tracking uygulanabilir
Transparent Huge Pages (THP) ve mTHP
- THP, sık erişilen belleği otomatik olarak büyük sayfalarda (2MiB vb.) toplayarak TLB verimliliğini artırır
khugepaged thread'i bitişik sayfaları birleştirir
- mTHP, 16KiB ve 64KiB gibi farklı boyutlarda değişken büyük sayfaları (folio) destekler
/proc/self/smaps içindeki AnonHugePages, FilePmdMapped alanlarından kullanım durumu görülebilir
- Sistem genelindeki ayarlar
/sys/kernel/mm/transparent_hugepage/ altında yönetilir
MADV_HUGEPAGE, MADV_NOHUGEPAGE ile alan bazında kontrol sağlanabilir
Kullanıcı alanı dirty tracking
userfaultfd ve PAGEMAP_SCAN kullanılarak yalnızca değişen sayfalar kopyalanabilir
- Çekirdek tek bir atomik işlemle hem tarama hem write-protect uygular
- Snapshot, live migration gibi senaryolarda verimlidir
TLB flush mekanizması
- x86'da TLB geçersiz kılma iki şekilde yapılır
INVLPG: tek sayfayı geçersiz kılar
- Page table kökünü yeniden yükleyerek tam flush
PCID ve INVPCID, süreç bazlı TLB etiket yönetimi ile gereksiz flush işlemlerini azaltır
tlb_single_page_flush_ceiling, çekirdeğin sayfa bazlı mı yoksa tam flush mı seçeceğini belirleyen eşik değerdir
Meltdown önlemi: Page Table Isolation (PTI)
- Meltdown, spekülatif yürütme sırasında çekirdek verisinin önbellek üzerinden sızabilmesine yol açan bir zafiyettir
- Linux, PTI (Page Table Isolation) ile kullanıcı ve çekirdek adres alanlarını ayırır
- Girişte
CR3 değiştirilerek yalnızca çekirdeğe ait page table kullanılır
PCID kullanılarak TLB flush etkisi en aza indirilir
- Varsayılan olarak etkindir;
nopti ile devre dışı bırakılabilir
Çekirdeğin güvenli eşleme değiştirme süreci
- Eşleme değiştirirken sıra şöyledir
- Önbellek kurallarını işleme
- Page table'ı güncelleme
- TLB'yi geçersiz kılma
- Çekirdek içi eşlemelerde (
vmap, vmalloc) de I/O öncesi ve sonrasında cache ve TLB eşzamanlaması yapılır
- Bazı mimarilerde kod kopyalandıktan sonra instruction cache flush gerekir
x86'da stack ve çağrı yapısı
- 64 bit modda RIP, RSP, RBP yazmaçları kullanılır; stack aşağı doğru büyür
- System V AMD64 ABI'ye göre argümanlar RDI, RSI, RDX, RCX, R8, R9, dönüş değeri ise RAX ile taşınır
- Kullanıcı modu ring 3, çekirdek ring 0 düzeyindedir; sistem çağrıları ve kesmeler kapılar üzerinden geçiş yapar
Hata durumları ve tanılama
mmap → EINVAL: dosya offset hizalama hatası
mmap → ENOMEM: sanal alan yetersizliği veya overcommit sınırı
- Dosya eşlemesine erişimde
SIGBUS: EOF ötesine erişim
mprotect(PROT_EXEC) → EACCES: noexec mount veya W^X politikası
fork() sonrası RSS artışı: CoW nedeniyle sayfa kopyalama
MAP_FIXED ile mevcut eşlemenin üzerine yazma → MAP_FIXED_NOREPLACE önerilir
Uygulama için kontrol listesi
- Hemen bellek edinmek için:
mmap + PROT_READ|PROT_WRITE + MAP_PRIVATE|MAP_ANONYMOUS
- Kod üretirken: W^X'i koru,
mprotect(PROT_READ|PROT_EXEC) kullan
- Dosya eşlerken:
offset sayfa hizalı olsun, EOF ötesine erişme
- Çok sayıda page fault varsa:
MADV_WILLNEED veya ön erişim kullan
- Bellek kullanımını analiz ederken:
/proc/<pid>/smaps_rollup → /proc/<pid>/maps
- Büyük süreçlerde fork: CoW'yi hesaba kat, çocuk süreçte
exec kullan
- Gecikmeye duyarlı ortamlarda: THP/mTHP,
mlock, TLB davranışını gözlemle
Henüz yorum yok.