Linux में process memory को आसान तरीके से समझना
(0xkato.xyz)- Linux की process memory संरचना को वास्तविक कामकाज के स्तर पर समझाया गया है, और virtual address space तथा physical memory के बीच संबंध को चरण-दर-चरण बताया गया है
- page table, VMA, mmap, page fault, CoW जैसे मुख्य mechanisms के आधार पर यह विस्तार से बताया गया है कि process memory को कैसे own और access करती है
/procfile system के जरिए प्रत्येक process की memory स्थिति को देखने के तरीके, औरpagemap,kpageflagsजैसे उन्नत diagnostic tools की भूमिका का परिचय दिया गया है- Transparent Huge Pages (THP), userfaultfd, PAGEMAP_SCAN जैसी आधुनिक kernel features के माध्यम से performance optimization और user-space dirty tracking तकनीकों पर चर्चा की गई है
- Meltdown mitigation PTI, TLB flush, W^X policy जैसी security और performance से जुड़ी kernel design principles को भी समझाया गया है, ताकि Linux memory management की समग्र समझ मिल सके
process memory की बुनियादी संरचना
- जब कोई program चलता है, तो ऐसा लगता है जैसे उसके पास एक बहुत बड़ी continuous memory हो, लेकिन वास्तव में Linux kernel इसे page units में dynamically बनाता है
- CPU page table को देखकर virtual address को physical frame में बदलता है
- यदि mapping नहीं हो, तो page fault होता है, और kernel नया page allocate करता है या error लौटाता है
- यदि physical RAM कम पड़ जाए, तो kernel unused pages को disk पर भेजता है या file pages हटाकर जगह बनाता है
/procएक virtual file system है जिसे kernel memory में बनाता है, और यह process तथा kernel state को files के रूप में दिखाता है
address space और VMA
- हर process के पास एक address space object होता है, जिसके अंदर कई VMA (Virtual Memory Area) होते हैं
- VMA एक continuous address range है, जिसमें समान permissions (R/W/X) और समान backend (anonymous memory या file) होता है
- page table वह संरचना है जिसे hardware refer करता है, और इसमें virtual pages और physical pages के बीच mapping information (PTE) stored रहती है
- address space में बदलाव तीन system calls से किया जाता है
mmap: नया region बनानाmprotect: permissions बदलनाmunmap: mapping हटाना
- page का basic unit 4KiB होता है, और कुछ systems 2MiB·1GiB के बड़े pages भी support करते हैं
/proc/self/maps से memory layout देखना
cat /proc/self/mapscommand से process की memory map देखी जा सकती है- इसमें executable की code·data·bss, heap, anonymous mappings, shared libraries, stack आदि दिखते हैं
[vdso]और[vvar]regions kernel द्वारा map किए गए तेज़ system calls के लिए code और data हैं
mmap कैसे काम करता है
mmapवास्तविक memory allocation नहीं करता, बल्कि address space के लिए एक वादा दर्ज करता है- page पहली access के समय allocate होते हैं
- file mapping के समय
offsetpage-aligned होना चाहिए, और file end से आगे access करने परSIGBUSहोता है MAP_SHAREDसीधे file में reflect होता है, जबकिMAP_PRIVATEcopy-on-write (CoW) के जरिए अलग page बनाता हैMAP_FIXED_NOREPLACEयह सुनिश्चित करता है कि अगर दिए गए address पर पहले से mapping हो तो call fail हो जाए, जिससे सुरक्षा बढ़ती है
पहली access और page fault
- नई mapping पर पहली access के समय अगर CPU को page table entry न मिले, तो page fault होता है
- kernel address validity, access permissions, और existence की जाँच करता है
- anonymous mapping हो तो 0 से भरा नया page allocate होता है, file mapping हो तो page cache से पढ़ा जाता है
- minor fault तब होता है जब data पहले से RAM में हो, और major fault तब जब disk I/O की ज़रूरत हो
- stack को guard page से सुरक्षित रखा जाता है, इसलिए बहुत नीचे की ओर access करने पर
SIGSEGVहो सकता है
fork() और MAP_PRIVATE का Copy-on-Write
forkके समय parent और child एक ही physical pages share करते हैं, और दोनों को read-only mark किया जाता है- write होने पर ही नया page copy किया जाता है ताकि दोनों अलग बने रहें
MAP_PRIVATEfile mapping भी इसी सिद्धांत पर काम करती है- संबंधित options
vfork: parent address space share करनाclone(CLONE_VM): thread बनानाMADV_DONTFORK,MADV_WIPEONFORK: child process में mapping को exclude करना या 0 से initialize करना
permissions बदलना और TLB invalidation
mprotectसे page permissions बदलने पर kernel VMA को split करता है और page table modify करता है, फिर TLB invalidate करता है- W^X policy के अनुसार कोई page एक ही समय पर writable और executable नहीं हो सकता
- TLB (Translation Lookaside Buffer) हाल की address translations का cache है, और invalidation होने पर थोड़ी देरी हो सकती है
/proc के जरिए विस्तार से निरीक्षण
/proc/<pid>/maps,smaps,smaps_rollupसे region-wise permissions, RSS, HugePage usage देखी जा सकती है/proc/<pid>/pagemappage-level state (present, swapped, PFN आदि) देता है, लेकिन PFN सामान्य users के लिए छिपा रहता है/proc/kpagecount,/proc/kpageflagsहर PFN के लिए mapping count और page properties (anonymous, file, dirty आदि) दिखाते हैंmincore,SEEK_DATA/SEEK_HOLEसे sparse files के data/hole regions की पहचान की जा सकती हैPAGEMAP_SCANऔरuserfaultfdको जोड़कर user-space dirty tracking लागू की जा सकती है
Transparent Huge Pages (THP) और mTHP
- THP बार-बार access होने वाली memory को अपने-आप बड़े pages (जैसे 2MiB) में समेटता है, जिससे TLB efficiency बेहतर होती है
khugepagedthread पास-पास के pages को merge करता है
- mTHP 16KiB·64KiB आदि आकारों के variable large pages (folio) को support करता है
/proc/self/smapsमेंAnonHugePages,FilePmdMappedसे उपयोग की जाँच की जा सकती है/sys/kernel/mm/transparent_hugepage/में system-wide settings manage की जाती हैंMADV_HUGEPAGE,MADV_NOHUGEPAGEसे region-level control संभव है
user-space dirty tracking
userfaultfdऔरPAGEMAP_SCANका उपयोग करके सिर्फ बदले हुए pages को copy किया जा सकता है- kernel एक atomic operation में scan और write-protect दोनों करता है
- snapshot, live migration जैसी स्थितियों में यह उपयोगी है
TLB flush mechanism
- x86 में TLB invalidation के दो तरीके हैं
INVLPG: एक single page को invalidate करना- page table root को reload करके full flush करना
PCIDऔरINVPCIDprocess-wise TLB tag management के जरिए अनावश्यक flush कम करते हैंtlb_single_page_flush_ceilingवह threshold है जिसके आधार पर kernel page-wise या full flush चुनता है
Meltdown mitigation: Page Table Isolation (PTI)
- Meltdown एक ऐसी vulnerability है जिसमें speculative execution के दौरान kernel data cache के माध्यम से leak हो सकता है
- Linux PTI (Page Table Isolation) के जरिए user और kernel address spaces को अलग करता है
- entry के समय
CR3switch करके kernel-only page table का उपयोग किया जाता है PCIDका उपयोग कर TLB flush को न्यूनतम रखा जाता है
- entry के समय
- यह default रूप से enabled रहता है, और
noptiसे disable किया जा सकता है
kernel की सुरक्षित mapping change प्रक्रिया
- mapping बदलते समय क्रम यह होता है
- cache rules लागू करना
- page table modify करना
- TLB invalidate करना
- kernel internal mappings (
vmap,vmalloc) में भी I/O से पहले और बाद में cache·TLB synchronization किया जाता है - कुछ architectures में code copy करने के बाद instruction cache flush की आवश्यकता होती है
x86 का stack और call structure
- 64-bit mode में RIP, RSP, RBP registers उपयोग होते हैं, और stack नीचे की ओर बढ़ता है
- System V AMD64 ABI के अनुसार arguments RDI, RSI, RDX, RCX, R8, R9 में जाते हैं, और return value RAX में आती है
- user mode ring 3 में चलता है, kernel ring 0 में, और system calls तथा interrupts gates के जरिए switch होते हैं
error situations और diagnosis
mmap→EINVAL: file offset alignment errormmap→ENOMEM: virtual space की कमी या overcommit limit- file mapping access पर
SIGBUS: EOF के पार access mprotect(PROT_EXEC)→EACCES:noexecmount या W^X policyfork()के बाद RSS बढ़ना: CoW के कारण page copiesMAP_FIXEDसे existing mapping overwrite होना →MAP_FIXED_NOREPLACErecommended
practical checklist
- तुरंत memory reserve करनी हो:
mmap+PROT_READ|PROT_WRITE+MAP_PRIVATE|MAP_ANONYMOUS - code generation के समय: W^X बनाए रखें,
mprotect(PROT_READ|PROT_EXEC) - file mapping के समय:
offsetको page-align करें, EOF के आगे access न करें - page faults अधिक हों:
MADV_WILLNEEDया pre-touch का उपयोग करें - memory usage analysis:
/proc/<pid>/smaps_rollup→/proc/<pid>/maps - बड़े process पर fork: CoW को ध्यान में रखें, child में
execउपयोग करें - latency-sensitive environment: THP/mTHP,
mlock, और TLB behavior observe करें
1 टिप्पणियां
Hacker News टिप्पणी
ऐसे छोटे व्याख्यात्मक लेख मुझे सच में बहुत पसंद हैं
भले ही बात पहले से पता हो, पढ़ते समय उसे एक बार फिर पक्का कर लेने में मदद मिलती है
“mmap, without the fog” जैसी पंक्ति देखकर, न जाने क्यों यह LLM के साथ मिलकर लिखा गया लेख लगता है, और इससे बेवजह बेचैनी और चिढ़ होती है
ऊपर से “without the fog” जैसी अजीब अभिव्यक्ति है, इसलिए और भी ChatGPT के साथ लिखा हुआ सा लगता है
Instruction pipelining की बात देखकर, मन करता है कि 6502 जैसी पुरानी सरल architecture के दौर में वापस चला जाए
तब चीज़ें जटिल mapping या proxy के बिना, लगभग “जैसी हैं वैसी” काम करती थीं
अगर तेज interconnects मिलें, तो शायद उस तरह की सादगी का सपना फिर देखा जा सकता है
लेकिन Meltdown, Spectre जैसी समस्याएँ देखें तो बढ़ती जटिलता की कीमत भी साफ़ दिखती है
अब जब Moore’s law अपनी सीमा के करीब दिख रहा है, तो सोचता हूँ कि क्या यह complexity trade-off वाकई सबसे अच्छा रास्ता है
मुझे नहीं लगता कि सादगी हमेशा बेहतर होती है
वेबसाइट को खतरनाक या असुरक्षित domain कहकर ब्लॉक किया गया दिख रहा है
VirusTotal जांच परिणाम देखें तो कोई समस्या नहीं दिखती
यह कहने का क्या मतलब है कि error report सिर्फ “noise” है?