এই পর্বে যা শিখবেন
- Virtualization কেন — consolidation, isolation, পরীক্ষা, পুরোনো সফটওয়্যার আর cloud; IBM থেকে VMware, Xen, KVM পর্যন্ত ইতিহাস
- Popek–Goldberg-এর তিন শর্ত আর উপপাদ্য, x86 কেন তা ভাঙত, আর তিনটি সমাধান — binary translation, paravirtualization, VT-x/AMD-V
- Type 1 আর type 2 hypervisor; Linux-এ KVM + QEMU-র গঠন, Windows-এ Hyper-V/WSL 2, Mac-এ Apple-এর framework
- Shadow page table বনাম EPT/NPT, ২৪ ধাপের walk-এর হিসাব; I/O-র অনুকরণ, virtio, passthrough আর SR-IOV; ballooning, KSM
- Live migration-এর হিসাব হাতে আর simulator-এ, snapshot, nested virtualization, VM-নিরাপত্তা — আর নিজের চোখে দেখা আমাদের কোড-চালানোর সার্ভারটি নিজেই VM কি না
১ · Virtualization কী — একটি যন্ত্রে অনেক কম্পিউটার
এতদিন আমরা দেখেছি একটি OS কীভাবে একটি কম্পিউটারের CPU, মেমরি আর ডিস্ক অনেকগুলো প্রসেসের মধ্যে ভাগ করে। প্রতিটি প্রসেস পায় নিজের virtual address space আর CPU-র পালা (পর্ব ৮, ৩৫)। এবার একই চিন্তা আরও এক ধাপ ওপরে: পুরো OS-গুলোকেই যদি একটি যন্ত্রে ভাগ করে চালানো যায়? একটি সার্ভারে একসাথে চলবে Ubuntu, Windows Server আর একটি পুরোনো CentOS — প্রত্যেকে ভাববে গোটা যন্ত্রটি তার একার।
এই কাজকে বলে virtualization. যে সফটওয়্যার কাজটি করে, তার নাম hypervisor বা VMM (virtual machine monitor). যে OS VM-এর ভেতরে চলে, সে guest; আর যে যন্ত্র বা OS-এর ওপর hypervisor বসে, সে host. Guest-এর চোখে আছে কিছু virtual CPU (vCPU), নির্দিষ্ট পরিমাণ “physical” মেমরি, একটি ডিস্ক আর একটি নেটওয়ার্ক কার্ড — আসলে সবই hypervisor-এর তৈরি করা ছবি।
ঢাকার একটি বহুতল ভবনের কথা ভাবুন। জমি একটাই, ভিত একটাই, পানি-বিদ্যুতের মূল লাইনও একটি। কিন্তু ভেতরে দশটি ফ্ল্যাট, প্রতিটির নিজের তালা, নিজের মিটার, নিজের সংসার। এক ফ্ল্যাটে আগুন লাগলে বা কেউ দেয়ালে রং বদলালে পাশের ফ্ল্যাটের কিছু হয় না। ভবনের কেয়ারটেকার ঠিক করেন কে কতটা পানি আর বিদ্যুৎ পাবে, কেউ মূল সুইচবোর্ডে হাত দিতে চাইলে তিনি নিজে সেটা সামলান। ভবন = ভৌত সার্ভার, ফ্ল্যাট = VM, ফ্ল্যাটের সংসার = guest OS, কেয়ারটেকার = hypervisor.
কেন এত আগ্রহ — পাঁচটি কারণ
🏢 Consolidation
অনেক সার্ভার বেশিরভাগ সময় অলস থাকে। দশটি আধা-অলস যন্ত্রের কাজ একটি শক্তিশালী যন্ত্রে দশটি VM-এ আনলে বিদ্যুৎ, জায়গা আর রক্ষণাবেক্ষণ — সবই কমে। একে বলে server consolidation.
🧱 Isolation
এক VM-এর crash, ভাইরাস বা ভুল কনফিগারেশন সাধারণত অন্য VM-এ পৌঁছায় না। প্রসেসের সীমানার চেয়ে এই সীমানা অনেক মোটা, কারণ প্রতিটি VM-এর kernel আলাদা।
🧪 পরীক্ষা ও শেখা
নতুন OS, ঝুঁকিপূর্ণ আপডেট বা ম্যালওয়্যার-বিশ্লেষণ একটি VM-এ; ভুল হলে snapshot-এ ফিরে যাওয়া। ছাত্রছাত্রীরা ল্যাপটপে VirtualBox-এ Linux চালিয়েই এই কোর্সের অনেক কিছু করতে পারেন।
🗄️ পুরোনো সফটওয়্যার আর cloud
পুরোনো OS ছাড়া চলে না এমন হিসাব-সফটওয়্যার নতুন হার্ডওয়্যারে VM-এ বাঁচিয়ে রাখা যায়। আর cloud-এর পুরো ব্যবসা — মিনিট হিসেবে ভাড়া দেওয়া সার্ভার — দাঁড়িয়ে আছে virtualization-এর ওপর।
ধারণাটি পুরোনো। ১৯৬০-এর দশকের মাঝামাঝি IBM-এর Cambridge Scientific Center-এ CP-40 তৈরি হয়, পরে System/360 Model 67-এর জন্য CP-67 (CP/CMS নামে পরিচিত) — প্রতিটি ব্যবহারকারী পেতেন নিজের একটি “virtual 360”. ১৯৭২ সালে IBM বাণিজ্যিকভাবে আনে VM/370, যার উত্তরসূরি আজও IBM-এর mainframe-এ চলে (সালগুলো উৎসভেদে এক-আধ বছর এদিক-ওদিক পাওয়া যায়)। ১৯৮০–৯০-এর দশকে PC যুগে ধারণাটি প্রায় ভুলে যাওয়া হয়, কারণ সস্তা যন্ত্রে এক মানুষ, এক OS. ১৯৯০-এর দশকের শেষে VMware x86-এ এটি ফিরিয়ে আনে; ২০০৩ সালে Xen, আর ২০০৭ সালে Linux kernel-এ যোগ হয় KVM (পর্ব ২-এ সংক্ষেপে দেখেছেন)।
২ · Popek–Goldberg-এর শর্ত — কখন VMM বানানো সম্ভব
১৯৭৪ সালে Gerald Popek আর Robert Goldberg একটি ছোট কিন্তু বিখ্যাত গবেষণাপত্রে প্রশ্নটি গাণিতিকভাবে বাঁধেন: কোন ধরনের CPU-তে একটি “ভালো” VMM বানানো যায়? তাঁরা একটি ভালো VMM-এর তিনটি শর্ত দেন — যাকে বলা হয় Popek–Goldberg requirements:
| শর্ত | মানে | ভাঙলে কী হয় |
|---|---|---|
| Equivalence (সমতুল্যতা) | VM-এর ভেতরে প্রোগ্রামের আচরণ আসল যন্ত্রের মতোই — শুধু সময় আর প্রাপ্ত সম্পদের পরিমাণ আলাদা হতে পারে | Guest OS ভুল ফল পায়, অদ্ভুতভাবে crash করে |
| Resource control (নিয়ন্ত্রণ) | সব আসল সম্পদের নিয়ন্ত্রণ VMM-এর হাতে; guest নিজে থেকে বাড়তি মেমরি বা ডিভাইস দখল করতে পারে না | এক VM অন্য VM বা host-এর ক্ষতি করতে পারে |
| Efficiency (দক্ষতা) | সাধারণ instruction-এর বেশিরভাগ সরাসরি আসল CPU-তে চলে, VMM-এর হস্তক্ষেপ ছাড়া | তখন এটি emulator — চলে, কিন্তু অনেক গুণ ধীর |
এরপর তাঁরা instruction-গুলোকে ভাগ করেন। Privileged instruction সেগুলো, যা user mode-এ চালালে CPU trap করে (exception দিয়ে kernel-এ যায়), আর kernel mode-এ চালালে স্বাভাবিকভাবে চলে (পর্ব ৫, ৪৮)। Sensitive instruction সেগুলো, যা যন্ত্রের নিয়ন্ত্রণ-অবস্থা বদলায় (যেমন interrupt চালু/বন্ধ, page table-এর ঠিকানা) বা যাদের ফল নির্ভর করে CPU কোন mode-এ আছে বা মেমরির কোথায় আছে তার ওপর। সব sensitive instruction privileged হবে, এমন কোনো নিয়ম hardware-এ আপনা-আপনি নেই — সেটিই আসল প্রশ্ন।
একটি প্রচলিত (third-generation) CPU-র জন্য VMM বানানো যায়, যদি sensitive instruction-এর সেট privileged instruction-এর সেটের উপসেট হয় — সংক্ষেপে sensitive ⊆ privileged.
কেন সত্য — যুক্তির খসড়া। VMM guest kernel-কে কম ক্ষমতায় (user mode-এ) চালায় আর নিজে থাকে আসল kernel mode-এ। এখন guest-এর যেকোনো instruction দুই রকমের হতে পারে:
- Sensitive নয়: এর ফল mode বা নিয়ন্ত্রণ-অবস্থার ওপর নির্ভর করে না, আর এটি নিয়ন্ত্রণ-অবস্থা বদলায়ও না। তাই সরাসরি আসল CPU-তে চালালে আসল যন্ত্রের মতোই ফল — equivalence আর efficiency দুটোই রক্ষা হয়, আর সম্পদও VMM-এর নিয়ন্ত্রণ থেকে বেরোয় না।
- Sensitive: শর্ত অনুযায়ী এটি privileged, আর guest আছে user mode-এ — তাই CPU অবশ্যই trap করবে। নিয়ন্ত্রণ যাবে VMM-এর কাছে। VMM তখন guest-এর virtual অবস্থার ওপর কাজটি অনুকরণ করে (যেমন guest-এর “interrupt বন্ধ” bit-টি নিজের টেবিলে বসায়), তারপর guest-কে পরের instruction থেকে চালায়। কোনো sensitive কাজ VMM-কে ফাঁকি দিয়ে আসল যন্ত্রে পৌঁছাতে পারে না — resource control রক্ষা হয়।
দুই ক্ষেত্রেই guest যা দেখে তা আসল যন্ত্রের সমান। উল্টো দিকটিও শিক্ষণীয়: কোনো একটি sensitive instruction যদি privileged না হয়, তবে guest সেটি চালালে trap হবে না, VMM জানতেই পারবে না, আর আসল CPU-র (user mode-এর) আচরণ guest-এর প্রত্যাশার সাথে মিলবে না। এই পদ্ধতির নাম trap-and-emulate.
একটি ব্যাংকের শাখায় নতুন অফিসার (guest kernel) বসেছেন, কিন্তু তাঁকে আসল ভল্টের চাবি দেওয়া হয়নি। নিয়ম: যে কাজে টাকা নড়ে বা হিসাব বদলায়, সেটির কাগজ ম্যানেজারের (VMM) টেবিলে যাবে — ম্যানেজার যাচাই করে নিজে কাজটি করবেন। এই ব্যবস্থা নিরাপদ থাকে যতক্ষণ প্রতিটি “সংবেদনশীল” কাজের জন্য ম্যানেজারের সই বাধ্যতামূলক। যদি একটি কাজও থাকে যা অফিসার চুপচাপ নিজের ডেস্কেই করে ফেলতে পারেন — আর তার ফলও অন্যরকম হয় — তাহলে ম্যানেজারের হিসাব আর বাস্তবতা মেলে না।
পুরোনো x86 কেন শর্তটি ভাঙত
১৯৭৮ সালের 8086 থেকে আসা x86-এর নকশায় virtualization মাথায় রাখা হয়নি। ২০০০ সালে John Robin আর Cynthia Irvine-এর একটি বিশ্লেষণে Pentium-এ এমন প্রায় ১৭টি instruction চিহ্নিত হয়, যা sensitive অথচ privileged নয়। পরিচিত কয়েকটি উদাহরণ:
- POPF: stack থেকে flags register বসায়। Kernel mode-এ এটি interrupt flag (IF) বদলাতে পারে; কম ক্ষমতার mode-এ IF বদলানোর অংশটি চুপচাপ উপেক্ষিত হয় — কোনো trap নেই। ফলে guest kernel ভাবে “interrupt চালু করলাম”, অথচ কিছুই ঘটেনি, আর VMM জানতেও পারে না।
- SGDT / SIDT: descriptor table-এর (GDT, IDT — পর্ব ৩৪) ঠিকানা পড়ে। User mode-এ চালালেও trap ছাড়াই আসল ঠিকানা ফেরত দেয় — guest দেখে VMM-এর টেবিলের ঠিকানা, নিজেরটা নয়। (পরে নিরাপত্তার কারণে নতুন CPU-তে UMIP নামে এগুলো user mode-এ আটকানোর ব্যবস্থা এসেছে।)
- PUSHF আর CS-এর মতো segment register পড়া: আসল flags আর বর্তমান privilege level (CS-এর নিচের দুই bit) ফাঁস করে দেয়, তাই guest বুঝে যায় সে আসলে ring 0-তে নেই।
তাই ২০০৫-এর আগে x86-এ বিশুদ্ধ trap-and-emulate অসম্ভব ছিল। তিনটি ভিন্ন সমাধান এসেছে — পরের অংশে।
৩ · তিনটি উত্তর — binary translation, paravirtualization আর VT-x
🔁 Binary translation (VMware, ১৯৯৮–৯৯)
Guest-এর user-স্তরের কোড সরাসরি চলে। কিন্তু guest kernel-এর কোড চালানোর আগে VMM ছোট ছোট খণ্ডে পড়ে, সমস্যাজনক instruction (যেমন POPF) বদলে নিরাপদ কোড বসায়, আর অনুবাদ cache-এ রেখে দেয়। Guest OS-এ কোনো পরিবর্তন লাগে না। এই কৌশলের নাম binary translation.
সুবিধা: যেকোনো OS · খরচ: জটিল VMM🤝 Paravirtualization (Xen, ২০০৩)
Guest kernel-কেই একটু বদলে দেওয়া হয়, যাতে সমস্যাজনক কাজের জায়গায় সে সরাসরি hypervisor-কে ডাকে — যেমন প্রসেস system call দিয়ে kernel-কে ডাকে। এই ডাকের নাম hypercall. পদ্ধতির নাম paravirtualization.
সুবিধা: দ্রুত · খরচ: guest বদলাতে হয়⚙️ Hardware সহায়তা (Intel VT-x ২০০৫, AMD-V ২০০৬)
CPU-তেই নতুন একটি mode যোগ হলো। Guest নিজের ring 0-তেই চলে, কিন্তু একটি “ঘেরাটোপ” mode-এ; সংবেদনশীল কাজে CPU নিজেই hypervisor-এ ফেরে। একে বলে hardware-assisted virtualization.
সুবিধা: সরল VMM, যেকোনো OSXen প্রকল্পটি University of Cambridge-এ শুরু হয়, আর ২০০৩ সালের গবেষণাপত্র “Xen and the Art of Virtualization” paravirtualization-কে জনপ্রিয় করে। Linux-কে বদলানো সহজ ছিল (সোর্স খোলা), Windows-কে নয় — paravirtualization-এর সীমা এখানেই। তবে চিন্তাটি হারায়নি: আজ প্রায় প্রতিটি VM-এ ডিভাইস paravirtual (অংশ ৬-এর virtio), আর CPU-র জন্য hardware সহায়তা — দুটোর মিশ্রণ।
VT-x-এর ভেতরে: root আর non-root mode
Intel VT-x (AMD-তে একই ধরনের AMD-V, যাকে SVM-ও বলে) CPU-তে দুটি জগৎ তৈরি করে। VMX root mode-এ চলে hypervisor; non-root mode-এ চলে guest. দুই জগতেই ring 0–3 আছে — তাই guest kernel নিজের ring 0-তে থাকে, POPF-এর মতো instruction guest-এর নিজের flags-এই ঠিকঠাক কাজ করে। আর যে কাজগুলো hypervisor নিজে দেখতে চায় (I/O port, কিছু control register, CPUID, HLT, external interrupt…), সেগুলো ঘটলে CPU একটি VM exit করে। Hypervisor কাজ সেরে VM entry (VMLAUNCH/VMRESUME instruction) দিয়ে guest-কে ফেরত পাঠায়। দুই জগতের অবস্থা থাকে মেমরির একটি কাঠামোয় — VMCS (virtual machine control structure; AMD-তে VMCB). নিচের ডায়াগ্রামে একটি পূর্ণ চক্র দেখুন:
- Guest চলছে
non-rootসাধারণ কোড সরাসরি - VM exit
out 0x3f8CPU অবস্থা VMCS-এ রাখে - VMM অনুকরণ করে
root modevirtual serial port - VM entry
VMRESUMEguest-এর অবস্থা ফেরত - Guest আবার
RIP + 1কিছুই টের পায়নি
mov al, 'A' ; সাধারণ instruction — কোনো exit নেই add rbx, 1 ; আসল গতিতে চলে mov dx, 0x3f8 ; port নম্বর ২৫৫-এর বেশি, তাই DX-এ রাখতে হয় out dx, al ; serial port-এ লেখা — hypervisor দেখতে চায়
guest-state area : RIP, RSP, RFLAGS, CR0/CR3/CR4, segment …
exit reason : 30 (I/O instruction)
exit qualification: port 0x3f8, size 1, direction OUT
instruction len : 1
host-state area → এখান থেকে hypervisor-এর RIP, CR3 লোড
switch (exit_reason) {
case EXIT_IO: vserial_write(port, guest.al); /* 'A' লগে/কনসোলে */
guest.rip += instr_len; /* পরের instruction */
break;
case EXIT_HLT: … case EXIT_CPUID: … case EXIT_EPT_VIOLATION: …
}
CPU যাচাই করে VMCS-এর guest-state ঠিক আছে কি না
guest-এর RIP, RSP, CR3 … লোড
mode: root → non-root
mov al, 'B' ; guest-এর চোখে: out-টি স্বাভাবিকভাবে শেষ হয়েছে out dx, al ; (DX এখনো 0x3f8) → আবার একটি VM exit
- Guest আসল গতিতে চলছে। CPU non-root mode-এ, guest kernel নিজের ring 0-তে।
mov,add-এর মতো সাধারণ instruction সরাসরি hardware-এ চলে — Popek–Goldberg-এর efficiency শর্ত। এবার guest serial port-এ (port 0x3f8) একটি অক্ষর লিখতে চায়। - VM exit. Hypervisor VMCS-এ আগেই বলে রেখেছে “I/O instruction হলে আমাকে ডাকো”। তাই
outচলার বদলে CPU guest-এর সব register VMCS-এর guest-state অংশে রাখে, কারণ (exit reason ৩০ — I/O) আর বিস্তারিত (কোন port, কত বাইট) লেখে, তারপর host-state থেকে hypervisor-এর অবস্থা লোড করে। এটি context switch-এর মতোই, শুধু hardware নিজে করে। - VMM অনুকরণ করে। Hypervisor exit reason দেখে বোঝে কী হয়েছে। এখানে আসল কোনো serial port নেই; আছে একটি software-এ বানানো virtual serial port — অক্ষর ‘A’ একটি লগ ফাইলে বা কনসোলে যায়। তারপর guest-এর RIP এক instruction এগিয়ে দেয়, যাতে একই
outআবার না চলে। - VM entry.
VMRESUMEচালাতেই CPU VMCS যাচাই করে guest-এর অবস্থা ফেরত আনে আর non-root mode-এ ঢোকে। একটি পূর্ণ exit → অনুকরণ → entry চক্রে সাধারণত কয়েকশো থেকে কয়েক হাজার CPU cycle লাগে (CPU-প্রজন্ম আর কাজভেদে) — তাই hypervisor-এর নকশার মূল লক্ষ্য exit-এর সংখ্যা কমানো। - Guest কিছুই টের পায়নি। তার চোখে
outএকটি স্বাভাবিক instruction, যা একটু ধীরে শেষ হলো। পরের অক্ষর ‘B’-তে আবার একই চক্র। প্রতি অক্ষরে একটি exit — এজন্যই অনুকরণ করা ডিভাইস ধীর, আর অংশ ৬-এ virtio এই exit-গুলো একসাথে জড়ো করে কমায়।
এবার একটি খেলনা VMM নিজে চালিয়ে দেখুন। একটি ছোট guest instruction-তালিকা দুইবার চালানো হচ্ছে: প্রথমবার এমন CPU-তে, যেখানে সব sensitive instruction trap করে; দ্বিতীয়বার পুরোনো x86-এর মতো, যেখানে POPF trap করে না। শেষে ফলাফল আসল যন্ত্রের (bare metal) সাথে মেলানো হয় — equivalence যাচাই।
// Toy trap-and-emulate: the guest kernel runs deprivileged; cli, mov_cr3, out, hlt
// (and popf, if the CPU makes it trap) cause VM exits that a tiny VMM emulates
const guest = [["add", 5], ["cli"], ["add", 3], ["mov_cr3", "0x2000"], ["popf", 1],
["out", "A"], ["add", 1], ["out", "B"], ["hlt"]];
function run(name, popfTraps) {
const v = { r1: 0, IF: 1, cr3: "0x1000", serial: "" }; // the guest's virtual CPU state
let exits = 0;
console.log(`--- ${name} ---`);
for (const [op, x] of guest) {
const text = (op + (x !== undefined ? " " + x : "")).padEnd(15);
if (op === "add") { v.r1 += x; console.log(`${text} native r1=${v.r1}`); continue; }
if (op === "popf" && !popfTraps) { // sensitive, NOT privileged
console.log(`${text} native (!!) IF write silently ignored in ring 3, IF=${v.IF}`); continue;
}
exits++; // VM exit -> VMM emulates
let what;
if (op === "cli") { v.IF = 0; what = "IF=0"; }
if (op === "popf") { v.IF = x; what = `IF=${x}`; }
if (op === "mov_cr3") { v.cr3 = x; what = `cr3=${x}`; }
if (op === "out") { v.serial += x; what = `serial="${v.serial}"`; }
if (op === "hlt") what = "vCPU halted";
console.log(`${text} VM EXIT #${exits} VMM emulates: ${what}` + (op === "hlt" ? "" : " -> VM entry"));
}
const bare = { r1: 9, IF: 1, cr3: "0x2000", serial: "AB" }; // same program on real ring 0
const same = Object.keys(bare).every(k => bare[k] === v[k]);
console.log(`exits=${exits} final IF=${v.IF} (bare metal: 1) equivalent? ${same ? "YES" : "NO"}`);
}
run("ISA where every sensitive instruction traps", true);
run("classic x86: POPF is sensitive but not privileged", false);আসল আউটপুট:
--- ISA where every sensitive instruction traps ---
add 5 native r1=5
cli VM EXIT #1 VMM emulates: IF=0 -> VM entry
add 3 native r1=8
mov_cr3 0x2000 VM EXIT #2 VMM emulates: cr3=0x2000 -> VM entry
popf 1 VM EXIT #3 VMM emulates: IF=1 -> VM entry
out A VM EXIT #4 VMM emulates: serial="A" -> VM entry
add 1 native r1=9
out B VM EXIT #5 VMM emulates: serial="AB" -> VM entry
hlt VM EXIT #6 VMM emulates: vCPU halted
exits=6 final IF=1 (bare metal: 1) equivalent? YES
--- classic x86: POPF is sensitive but not privileged ---
add 5 native r1=5
cli VM EXIT #1 VMM emulates: IF=0 -> VM entry
add 3 native r1=8
mov_cr3 0x2000 VM EXIT #2 VMM emulates: cr3=0x2000 -> VM entry
popf 1 native (!!) IF write silently ignored in ring 3, IF=0
out A VM EXIT #3 VMM emulates: serial="A" -> VM entry
add 1 native r1=9
out B VM EXIT #4 VMM emulates: serial="AB" -> VM entry
hlt VM EXIT #5 VMM emulates: vCPU halted
exits=5 final IF=0 (bare metal: 1) equivalent? NO
প্রথম চালানোয় ৯টি instruction-এর ৩টি (add) সরাসরি চলেছে, বাকি ৬টিতে VM exit — VMM প্রতিটি guest-এর virtual অবস্থায় (IF, cr3, serial) বসিয়েছে। শেষ অবস্থা আসল যন্ত্রের সমান: equivalent? YES. দ্বিতীয় চালানোয় একই প্রোগ্রাম, শুধু POPF এখন sensitive কিন্তু privileged নয়: ring 3-এ IF-এ লেখা চুপচাপ উপেক্ষিত, VMM টেরই পেল না (exit একটি কম, ৫টি), আর guest-এর IF রয়ে গেল 0 — অথচ আসল যন্ত্রে হতো 1. Guest kernel ভাবছে interrupt চালু, কিন্তু আসলে বন্ধ; বাস্তবে এমন guest timer interrupt না পেয়ে আটকে যেতে পারে। equivalent? NO — Popek–Goldberg-এর উপপাদ্যের উল্টো দিকটি চোখের সামনে।
৪ · Type 1 আর type 2 — hypervisor কোথায় বসে
পর্ব ২-এ নাম দুটি শুনেছেন। ১৯৭০-এর দশকে Goldberg-এর শ্রেণিবিভাগ থেকেই এই নাম এসেছে:
| দিক | Type 1 (bare-metal) | Type 2 (hosted) |
|---|---|---|
| কোথায় চলে | সরাসরি হার্ডওয়্যারে; নিজেই একরকম ছোট OS | একটি সাধারণ OS-এর (Windows, macOS, Linux) ওপর একটি অ্যাপ হিসেবে |
| উদাহরণ | VMware ESXi, Xen, Microsoft Hyper-V, (তর্কসাপেক্ষে) KVM | Oracle VirtualBox, VMware Workstation/Fusion, Parallels Desktop |
| ডিভাইস driver | নিজের (ESXi) বা একটি বিশেষ VM-এর (Xen-এর dom0, Hyper-V-র root partition) | host OS-এর driver-ই ব্যবহার করে |
| কোথায় দেখবেন | ডেটা সেন্টার, cloud, ব্যাংকের সার্ভার রুম | ডেভেলপারের ল্যাপটপ, ক্লাসরুম, পরীক্ষা |
KVM কোন দলে? KVM (Kernel-based Virtual Machine) একটি Linux kernel module; ২০০৭ সালে Linux 2.6.20-এ যোগ হয়। Module লোড হলে Linux kernel নিজেই hypervisor হয়ে যায় — hardware-এ সরাসরি বসা, তাই অনেকে type 1 বলেন। আবার host-এ একটি পূর্ণ সাধারণ OS (Linux) চলছে, VM-গুলো সেখানে সাধারণ প্রসেস হিসেবে দেখা যায় — তাই অনেকে type 2 বলেন। আসল শিক্ষা: শ্রেণিবিভাগটি সরলীকরণ; গুরুত্বপূর্ণ প্রশ্ন হলো কোন কোড সবচেয়ে বেশি ক্ষমতায় চলে আর কতটা বড় (অর্থাৎ নিরাপত্তার ভিত কতটা ছোট)।
Linux-এ KVM + QEMU — কে কী করে
KVM শুধু CPU আর মেমরির virtualization সামলায়। বাকি “যন্ত্র” — BIOS/UEFI firmware, ডিস্ক, নেটওয়ার্ক কার্ড, USB — বানায় user space-এর একটি প্রোগ্রাম, সাধারণত QEMU (২০০৩ সালে Fabrice Bellard-এর শুরু করা emulator). প্রতিটি VM host-এর চোখে একটি QEMU প্রসেস; প্রতিটি vCPU সেই প্রসেসের একটি thread. QEMU /dev/kvm ডিভাইস ফাইল খুলে ioctl দিয়ে KVM-কে আদেশ দেয়। মূল লুপটি দেখতে এমন (সরলীকৃত, Linux-এর আসল KVM API অনুযায়ী):
int kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
int vm = ioctl(kvm, KVM_CREATE_VM, 0);
void *mem = mmap(NULL, 0x200000, PROT_READ | PROT_WRITE, /* guest-এর "RAM" */
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
struct kvm_userspace_memory_region r = { .slot = 0, .guest_phys_addr = 0,
.memory_size = 0x200000, .userspace_addr = (unsigned long)mem };
ioctl(vm, KVM_SET_USER_MEMORY_REGION, &r);
int vcpu = ioctl(vm, KVM_CREATE_VCPU, 0);
struct kvm_run *run = mmap(NULL, ioctl(kvm, KVM_GET_VCPU_MMAP_SIZE, 0),
PROT_READ | PROT_WRITE, MAP_SHARED, vcpu, 0);
/* … guest-এর কোড mem-এ কপি, KVM_SET_SREGS / KVM_SET_REGS দিয়ে register … */
for (;;) {
ioctl(vcpu, KVM_RUN, 0); /* VM entry; ফেরে এমন exit-এ যা kernel নিজে সামলায় না */
switch (run->exit_reason) {
case KVM_EXIT_IO: /* guest IN/OUT করেছে: ডিভাইস অনুকরণ — QEMU-র কাজ */
if (run->io.direction == KVM_EXIT_IO_OUT && run->io.port == 0x3f8)
putchar(*((char *)run + run->io.data_offset));
break;
case KVM_EXIT_MMIO: /* ডিভাইসের মেমরি-ঠিকানা ছুঁয়েছে */ break;
case KVM_EXIT_HLT: return 0;
default: fprintf(stderr, "unhandled exit %d\n", run->exit_reason); return 1;
}
}খেয়াল করুন, অনেক exit (যেমন EPT-র page fault, CPUID, কিছু MSR) KVM kernel-এর ভেতরেই সেরে ফেলে, user space-এ ফেরেই না — তাতে খরচ কম। শুধু ডিভাইস-অনুকরণের মতো কাজে KVM_RUN ফেরে QEMU-তে। Cloud-এ QEMU-র বদলে আরও ছোট user-space VMM-ও ব্যবহার হয় (যেমন Firecracker, Cloud Hypervisor) — microVM নিয়ে পর্ব ৫২-তে।
অন্য OS-এ
Hyper-V (প্রথম আসে Windows Server 2008-এর সাথে) একটি type 1 hypervisor. চালু করলে একটি মজার ঘটনা ঘটে: আপনার পরিচিত Windows-টিও তখন hypervisor-এর ওপর একটি বিশেষ VM — “root partition”, যার হাতে ডিভাইস driver থাকে। WSL 2 একটি হালকা “utility VM”-এ আসল Linux kernel চালায়; Windows-এর কিছু নিরাপত্তা-ব্যবস্থা (VBS, Credential Guard) আর Windows Sandbox-ও এর ওপর দাঁড়ানো। একই সাথে পুরোনো VirtualBox সংস্করণ চালাতে সমস্যা হতো এজন্যই — এখন সেগুলো Windows-এর hypervisor API দিয়ে চলতে পারে।
PS> systeminfo | Select-String "Hyper-V"
Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.Apple দুটি স্তর দেয়: নিচে Hypervisor.framework (vCPU আর মেমরির নিম্নস্তরের API, ২০১৪-র দিকে macOS 10.10 থেকে), আর ওপরে Virtualization.framework (macOS 11 থেকে), যা দিয়ে কয়েক ডজন লাইনে virtio ডিভাইসসহ পূর্ণ Linux বা macOS VM বানানো যায়। Apple silicon Mac-এ UTM, Parallels-এর মতো অ্যাপ এর ওপর চলে; ARM Mac-এ সাধারণত ARM-এর OS চালানো হয় — x86 OS চালাতে হলে পুরো emulation লাগে, যা অনেক ধীর।
$ sysctl kern.hv_support
kern.hv_support: 1বড় cloud-গুলো নিজেদের hypervisor নিজেদের মতো সাজায়। AWS-এর Nitro ব্যবস্থায় (২০১৭ সালের দিকে চালু) নেটওয়ার্ক, স্টোরেজ আর ব্যবস্থাপনার কাজ সরিয়ে নেওয়া হয়েছে আলাদা বিশেষ কার্ডে, আর মূল CPU-তে থাকে KVM-ভিত্তিক একটি খুব ছোট hypervisor — AWS-এর প্রকাশিত বর্ণনা অনুযায়ী। লক্ষ্য দুটি: গ্রাহকের VM প্রায় পুরো CPU পায়, আর hypervisor ছোট হওয়ায় আক্রমণের জায়গা কমে। Google Cloud আর Azure-ও KVM বা Hyper-V-ভিত্তিক নিজস্ব রূপ ব্যবহার করে বলে জানা যায়।
নিজের চোখে দেখুন — আমাদের কোড-চালানোর সার্ভার কি নিজেই VM?
এই কোর্সের runnable কোড চলে একটি অনলাইন সার্ভারের container-এ। নিচের script ভেতর থেকে কয়েকটি সূত্র দেখে: CPU-র flag, firmware-এর পরিচয় (DMI), /dev/kvm আর container-এর চিহ্ন। কোনো কিছু না পেলে script ভেঙে না পড়ে বার্তা দেয়।
echo "== 1. CPU model and virtualization flags =="
grep -m1 'model name' /proc/cpuinfo
echo "lines with vmx/svm: $(grep -c -E 'vmx|svm' /proc/cpuinfo)"
if grep -m1 -qw hypervisor /proc/cpuinfo; then
echo "'hypervisor' flag: present (CPUID says: you are a guest)"
else
echo "'hypervisor' flag: absent"
fi
echo "== 2. firmware (DMI) product name and vendor =="
cat /sys/class/dmi/id/product_name 2>/dev/null || echo "(not readable here)"
cat /sys/class/dmi/id/sys_vendor 2>/dev/null
echo "== 3. systemd-detect-virt =="
v=$(systemd-detect-virt 2>/dev/null); echo "vm/container: ${v:-(tool not available)}"
echo "== 4. /dev/kvm (can WE run VMs?) =="
ls -l /dev/kvm 2>/dev/null || echo "/dev/kvm: not present"
echo "== 5. container hints =="
[ -f /.dockerenv ] && echo "/.dockerenv exists" || echo "no /.dockerenv"
echo "process with PID 1: $(cat /proc/1/comm)"
dmesg 2>/dev/null | grep -i -m2 hypervisor || echo "(dmesg: no access or no match)"একবার চালানোর আসল ফল:
== 1. CPU model and virtualization flags ==
model name : AMD EPYC-Rome Processor
lines with vmx/svm: 0
'hypervisor' flag: present (CPUID says: you are a guest)
== 2. firmware (DMI) product name and vendor ==
[a cloud host's product name]
[a cloud host's company name]
== 3. systemd-detect-virt ==
vm/container: (tool not available)
== 4. /dev/kvm (can WE run VMs?) ==
/dev/kvm: not present
== 5. container hints ==
no /.dockerenv
process with PID 1: podman-init
(dmesg: no access or no match)
সূত্রগুলো একসাথে পড়লে ছবিটা পরিষ্কার। hypervisor flag আছে — এটি CPUID-এর একটি bit, যা hypervisor তার guest-কে দেখায়; আসল (bare-metal) যন্ত্রে সাধারণত থাকে না। DMI-তে product আর vendor-এর ঘরে একটি cloud host-এর পণ্যের নাম আর কোম্পানির নাম (এখানে বন্ধনীতে আড়াল করা; আপনি চালালে আসল নাম দেখবেন) — অর্থাৎ এটি সম্ভবত একটি cloud host-এ ভাড়া করা VM. vmx/svm শূন্য — এই guest-কে hardware virtualization দেখানো হয়নি (nested virtualization বন্ধ, অংশ ৯), আর /dev/kvm-ও নেই, তাই এখানে আমরা নিজেরা VM চালাতে পারব না। শেষে PID 1 হলো podman-init — আমরা একটি Podman container-এর ভেতরে। অর্থাৎ দুই স্তর: VM-এর ভেতরে container, তার ভেতরে আমাদের shell. systemd-detect-virt এই ছোট container-এ নেই, আর dmesg থেকেও কিছু মেলেনি (kernel-এর লগ সাধারণ ব্যবহারকারীর জন্য প্রায়ই বন্ধ থাকে) — “না পাওয়াও” একরকম তথ্য। আপনার ল্যাপটপে চালালে ফল ভিন্ন হবে; Windows-এ Hyper-V/VBS চালু থাকলে WSL-এর ভেতরে তো বটেই, অনেক সময় host-এর দিক থেকেও hypervisor-এর চিহ্ন দেখা যায়।
একই প্রশ্ন সরাসরি CPU-কে করা যায় CPUID instruction দিয়ে। Leaf 1-এর ECX register-এর bit 31 “hypervisor present” bit; থাকলে leaf 0x40000000 থেকে hypervisor নিজের নাম জানায়।
#include <stdio.h>
#include <string.h>
#include <cpuid.h>
static void vendor_at(unsigned int leaf) { /* hypervisor's own CPUID leaves */
unsigned int a, b, c, d;
char v[13];
__cpuid(leaf, a, b, c, d);
memcpy(v, &b, 4); memcpy(v + 4, &c, 4); memcpy(v + 8, &d, 4);
v[12] = '\0';
printf("leaf 0x%x: vendor \"%s\", max leaf 0x%x\n", leaf, v, a);
}
int main(void) {
unsigned int a, b, c, d;
__get_cpuid(1, &a, &b, &c, &d);
int hv = (c >> 31) & 1; /* leaf 1, ECX bit 31 */
printf("leaf 1 ECX bit 31 (hypervisor present): %d\n", hv);
printf("leaf 1 ECX bit 5 (Intel VMX visible) : %d\n", (c >> 5) & 1);
if (__get_cpuid(0x80000001, &a, &b, &c, &d))
printf("leaf 0x80000001 ECX bit 2 (AMD SVM) : %d\n", (c >> 2) & 1);
if (!hv) {
printf("hypervisor: not found (bare metal, or a hidden hypervisor)\n");
return 0;
}
printf("hypervisor: found\n");
vendor_at(0x40000000);
vendor_at(0x40000100); /* KVM moves here when it also offers Hyper-V */
return 0;
}আসল আউটপুট:
leaf 1 ECX bit 31 (hypervisor present): 1
leaf 1 ECX bit 5 (Intel VMX visible) : 0
leaf 0x80000001 ECX bit 2 (AMD SVM) : 0
hypervisor: found
leaf 0x40000000: vendor "Microsoft Hv", max leaf 0x40000005
leaf 0x40000100: vendor "KVMKVMKVM", max leaf 0x40000101
Bit 31 = 1, তাই hypervisor আছে; VMX আর SVM bit 0 — shell script-এর ফলের সাথে মিলে গেল। মজার অংশটি নামে: leaf 0x40000000-এ লেখা “Microsoft Hv”, অথচ পরের ব্লকে (0x40000100) “KVMKVMKVM”. কারণ KVM/QEMU চাইলে Hyper-V-র paravirtual interface-ও নকল করে দেখায় (Windows guest তাতে দ্রুত চলে); তখন Hyper-V-র পরিচয় বসে প্রথম ব্লকে, আর KVM নিজের পরিচয় সরিয়ে নেয় 0x40000100-এ। অর্থাৎ এই সার্ভারের নিচে আসলে KVM. শিক্ষা: একটি সূত্র দেখে সিদ্ধান্ত নয়, কয়েকটি মিলিয়ে দেখা — আর hypervisor চাইলে নিজেকে লুকাতে বা অন্যের মতো সাজাতেও পারে।
৫ · মেমরির virtualization — shadow page table থেকে EPT
প্রসেসের জন্য OS অনুবাদ করে virtual → physical (পর্ব ৩২–৩৩)। VM-এ একটি স্তর বেশি। Guest OS নিজের page table বানায়: guest virtual (gVA) → guest physical (gPA). কিন্তু guest-এর “physical” মেমরি আসল নয় — hypervisor সেটিকে host-এর কোনো ফ্রেমে রেখেছে: gPA → host physical (hPA). আসল CPU-কে শেষ পর্যন্ত hPA দিতে হবে। দুটি উপায় এসেছে।
👥 Shadow page table (পুরোনো, software)
Hypervisor guest-এর টেবিল পড়ে নিজের একটি “ছায়া” টেবিল বানায়, যাতে সরাসরি gVA → hPA লেখা থাকে, আর আসল CR3-এ সেটিই বসায়। Guest-এর টেবিলগুলো লেখা-নিষেধ (write-protect) করে রাখে, যাতে guest বদলালেই trap হয় আর ছায়াটিও মেলানো যায়। TLB miss-এ walk সাধারণ চার ধাপের, কিন্তু প্রতিটি টেবিল-বদল, প্রসেস তৈরি বা context switch-এ VM exit — page table ঘন ঘন বদলালে খুব দামি। এটি shadow page table.
🧩 EPT / NPT (hardware, ২০০৭–০৮ থেকে)
CPU নিজেই দুটি টেবিল হাঁটে: guest-এর টেবিল (guest CR3 থেকে) আর hypervisor-এর টেবিল (EPT pointer থেকে)। Guest নিজের টেবিল যত খুশি বদলাক, exit লাগে না। AMD-তে প্রথমে Barcelona-প্রজন্মের Opteron-এ NPT, Intel-এ Nehalem-প্রজন্মে EPT. সাধারণ নাম nested paging. দাম: TLB miss অনেক দামি — নিচে দেখুন।
পর্ব ৩৩-এর “আরও গভীরে” অংশে সংখ্যাটি শুনেছিলেন — ২৪. এবার হিসাবটি ধাপে ধাপে দেখি। ধরুন guest আর host দুটিই x86-64-এর চার স্তরের page table ব্যবহার করে, কোনো cache বা TLB-তে কিছু নেই। মূল কথা: guest-এর টেবিলগুলো নিজেও guest-physical মেমরিতে থাকে, তাই প্রতিটি guest-টেবিল পড়ার আগে তার ঠিকানাটিকেও host-এর টেবিল দিয়ে অনুবাদ করতে হয়। এই হাঁটার নাম two-dimensional page walk.
1 gCR3 (gPA) → host walk → read guest L4 entry2 gL4 entry (gPA of L3) → host walk → read gL33 gL3 entry (gPA of L2) → host walk → read gL24 gL2 entry (gPA of L1) → host walk → read gL15 gL1 entry = data gPA → host walk → hPA6 read the data; TLB ← (gVA → hPA)
| host টেবিল-পড়া | |
| guest টেবিল-পড়া | |
| মোট walk-পড়া | |
| ডেটাসহ মোট |
- প্রথম guest-স্তর — ৫টি পড়া। Guest-এর CR3-এ যে ঠিকানা, সেটি guest-physical. তাই guest-এর L4 টেবিল পড়ার আগে এই gPA-কে host-এর চার স্তরের টেবিল দিয়ে অনুবাদ করতে হলো — ৪টি পড়া (গ্রিডের ১–৪)। তারপর আসল guest L4 entry পড়া — ৫ নম্বর।
- দ্বিতীয় স্তর — আরও ৫টি, মোট ১০। L4 entry-তে আছে guest L3 টেবিলের ঠিকানা, আবার একটি gPA. আবার host-এর চার ধাপ (৬–৯), তারপর guest L3 entry (১০)।
- তৃতীয় স্তর — মোট ১৫। একই নকশা: L3 entry → L2 টেবিলের gPA → host walk (১১–১৪) → guest L2 entry (১৫)। প্রতিটি guest-স্তরের দাম (৪ + ১) = ৫।
- চতুর্থ স্তর — মোট ২০। Host walk (১৬–১৯), তারপর guest L1 entry (২০)। এই entry-তে ডেটার guest-physical ঠিকানা পাওয়া গেল — guest-এর অনুবাদ শেষ, কিন্তু এখনো আসল ঠিকানা মেলেনি।
- ডেটার ঠিকানার শেষ অনুবাদ — মোট ২৪। ডেটার gPA-কেও host-এর চার ধাপে অনুবাদ (২১–২৪) — এবার hPA হাতে। তাই walk-এর পড়া = ৪ × (৪ + ১) + ৪ = ২৪ = (৪ + ১)(৪ + ১) − ১. সাধারণ সূত্র: guest-এ n, host-এ m স্তর হলে (n + 1)(m + 1) − 1.
- ডেটা পড়া — ২৫তম ছোঁয়া। এবার আসল ডেটা পড়া হলো। VM ছাড়া একই miss-এ লাগত ৪টি walk-পড়া + ১টি ডেটা = ৫টি; এখানে ২৫টি। রক্ষা করে TLB: অনুবাদটি সরাসরি gVA → hPA হিসেবে TLB-তে বসে, তাই পরের hit-এ মাত্র একটি ছোঁয়া। CPU-র paging-structure cache-ও মাঝের অনেক ধাপ মনে রাখে, তাই বাস্তবে গড় খরচ অনেক কম।
Huge page কেন VM-এ আরও জরুরি: host যদি 2 MiB page ব্যবহার করে, host-এর টেবিল এক স্তর কমে (m = ৩): (৪ + ১)(৩ + ১) − ১ = ১৯. দুই দিকেই 2 MiB হলে (৩ + ১)(৩ + ১) − ১ = ১৫. উল্টো দিকে, পাঁচ স্তরের paging (পর্ব ৩৩) দুই দিকে চালু থাকলে (৫ + ১)(৫ + ১) − ১ = ৩৫. তাই cloud-এ host-এর দিকে huge page প্রায় নিয়মিত ব্যবস্থা। আর tagged TLB-র কারণে (AMD-V-তে শুরু থেকেই ASID, Intel-এ ২০০৮-এর দিকে VPID) VM বদলালেও TLB পুরো খালি করতে হয় না।
৬ · I/O-র virtualization — অনুকরণ, virtio আর সরাসরি ডিভাইস
CPU আর মেমরির পরে আসে ডিস্ক, নেটওয়ার্ক কার্ড, GPU. এখানে তিনটি মূল পথ, আর প্রত্যেকটি গতি, নমনীয়তা আর নিরাপত্তার মধ্যে আলাদা আপস করে।
Device emulation: hypervisor (সাধারণত QEMU) একটি বাস্তব, পুরোনো, সবার চেনা ডিভাইসের হুবহু নকল বানায় — যেমন Intel-এর e1000 নেটওয়ার্ক কার্ড বা IDE ডিস্ক। Guest-এর সাধারণ driver-ই কাজ করে, guest-এ কিছু ইনস্টল লাগে না। কিন্তু driver প্রতিটি register ছুঁলেই VM exit, আর একটি নেটওয়ার্ক প্যাকেট পাঠাতে অনেকবার register ছুঁতে হয় — ধীর। পুরোনো OS বা ইনস্টলের প্রথম মুহূর্তে কাজের।
virtio একটি খোলা মানদণ্ড (Rusty Russell-এর ২০০৭–০৮ সালের কাজ থেকে, পরে OASIS-এর মানদণ্ড): guest জানে সে VM-এ আছে, তাই নকল হার্ডওয়্যারের ভান না করে guest আর hypervisor মেমরিতে একটি ভাগ করা সারি (virtqueue — পর্ব ৩৯-এর descriptor ring-এর মতো) রাখে। Guest অনেকগুলো অনুরোধ সারিতে রেখে একবার “ঘণ্টা” (notify) বাজায় — একটি exit-এ অনেক কাজ। Linux-এ virtio driver kernel-এর অংশ; Windows-এ আলাদা driver ইনস্টল করতে হয়। আজকের বেশিরভাগ Linux VM-এর ডিস্ক আর নেটওয়ার্ক virtio.
Device passthrough: একটি আসল PCI ডিভাইস (যেমন একটি GPU বা NIC) পুরোপুরি একটি VM-কে দিয়ে দেওয়া; guest-এর নিজের driver সরাসরি হার্ডওয়্যার চালায়, প্রায় আসল গতিতে। বিপদ: ডিভাইসটি DMA দিয়ে যেকোনো physical মেমরিতে লিখতে পারে! তাই IOMMU (Intel VT-d, AMD-Vi) বাধ্যতামূলক — এটি ডিভাইসের DMA ঠিকানা অনুবাদ করে শুধু সেই VM-এর মেমরিতে সীমিত রাখে। Linux-এ এটি করা হয় VFIO দিয়ে। SR-IOV (PCI-SIG-এর মানদণ্ড) এক ধাপ এগিয়ে: একটি NIC নিজেকে অনেকগুলো হালকা “virtual function”-এ ভাগ করে, প্রতিটি আলাদা VM-কে দেওয়া যায়। দাম: VM তখন সেই নির্দিষ্ট হার্ডওয়্যারে বাঁধা — live migration কঠিন হয়।
| পথ | গতি | guest-এ যা লাগে | live migration | মূল ঝুঁকি |
|---|---|---|---|---|
| পূর্ণ অনুকরণ | ধীর (অনেক exit) | কিছু না | সহজ | বড় অনুকরণ-কোড = বাগের জায়গা |
| virtio | দ্রুত | virtio driver | সহজ | ছোট, কিন্তু তবু অনুকরণ-কোড |
| Passthrough / SR-IOV | প্রায় আসল | হার্ডওয়্যারের driver | কঠিন | IOMMU ছাড়া চলবে না; ডিভাইসের firmware-ও বিশ্বাস করতে হয় |
৭ · মেমরি overcommit, snapshot আর clone
৬৪ GB RAM-এর একটি সার্ভারে কি ৮ GB করে দশটি VM চালানো যায়? যায় — যদি সবাই একসাথে পুরো মেমরি না ছোঁয়। একে বলে VM-স্তরের overcommit, পর্ব ৩৫-এর প্রসেস-স্তরের overcommit-এরই বড় রূপ। ২০০২ সালে Carl Waldspurger-এর VMware ESX বিষয়ক বিখ্যাত গবেষণাপত্রে নিচের প্রথম দুটি কৌশল জনপ্রিয় হয়:
- Ballooning: Guest-এর ভেতরে একটি ছোট driver (“বেলুন”) থাকে। Host-এর মেমরি কম পড়লে hypervisor বেলুন ফোলাতে বলে — driver guest-এর কাছে মেমরি চেয়ে নেয় (guest নিজের নিয়মে cache ফেলে বা swap করে দেয়), আর সেই page-গুলো hypervisor-কে ফেরত দেয়। সুবিধা: কোন page ফেলা নিরাপদ, সেটা guest নিজেই সবচেয়ে ভালো জানে। এটি memory ballooning; Linux-এ virtio-balloon.
- Page sharing: দশটি VM-এ একই Ubuntu চললে অনেক page হুবহু এক (একই kernel কোড, একই library, শূন্যে ভরা page). Hypervisor বিষয়বস্তু মিলিয়ে এমন page-এর একটিমাত্র কপি রাখে, শুধু-পড়ার অনুমতিতে; কেউ লিখলে copy-on-write. Linux-এ এর নাম KSM (Kernel Same-page Merging). নিরাপত্তার দিক থেকে সতর্কতা: মেলানো page-এ লিখতে বেশি সময় লাগে — সেই সময় মেপে অন্য VM-এর তথ্যের আভাস পাওয়ার গবেষণা দেখানো হয়েছে, তাই অনেক cloud ভিন্ন গ্রাহকের মধ্যে এটি বন্ধ রাখে।
- Host-স্তরে swapping: শেষ উপায় — hypervisor নিজেই guest-এর page ডিস্কের swap-এ পাঠায়। Guest জানে না কোন page বাইরে, তাই সে হয়তো ঠিক সেই page-টিই নিজে swap করতে চাইবে — দুইবার ডিস্ক। এজন্য এটি ধীর, শেষ ভরসা।
$ cat /sys/kernel/mm/ksm/run /sys/kernel/mm/ksm/pages_sharing
1
183402 # এতগুলো page একটি কপি ভাগ করে চলছে
$ virsh setmem web01 4G --live # balloon দিয়ে চলন্ত VM-এর মেমরি 4 GiB-এ নামানোSnapshot আর clone. VM-এর পুরো অবস্থা আসলে কয়েকটি ফাইল: ডিস্ক-image, কনফিগারেশন, আর (চাইলে) মেমরি আর ডিভাইসের অবস্থা। VM snapshot সেই মুহূর্তের ছবি; qcow2-এর মতো ফরম্যাটে এটি copy-on-write — পরের লেখাগুলো নতুন স্তরে যায়, পুরোনো ছবি অক্ষত থাকে (পর্ব ৪৪-এর COW file system-এর মতো চিন্তা)। ঝুঁকিপূর্ণ আপডেটের আগে snapshot, ভুল হলে ফিরে যাওয়া। Clone: একটি “golden image” থেকে অনেক VM, প্রতিটি নিজের পাতলা স্তর নিয়ে — শ্রেণিকক্ষের ৪০টি ল্যাব-VM কয়েক সেকেন্ডে। সতর্কতা: clone-এর ভেতরে hostname, SSH host key, machine-id, এমনকি random-সংখ্যার বীজও এক থেকে যায় — চালুর আগে সেগুলো নতুন করে বানাতে হয় (Linux-এ cloud-init বা virt-sysprep, Windows-এ sysprep). আর snapshot ব্যাকআপ নয় — একই ডিস্কে থাকে, ডিস্ক গেলে সবই যায়।
$ qemu-img snapshot -c before-upgrade web01.qcow2 # snapshot তৈরি
$ qemu-img create -f qcow2 -b golden.qcow2 -F qcow2 lab07.qcow2 # পাতলা clone
$ qemu-img info lab07.qcow2 | grep backing
backing file: golden.qcow2৮ · Live migration — চলন্ত VM-কে অন্য যন্ত্রে সরানো
একটি সার্ভারের হার্ডওয়্যার বদলাতে হবে, কিন্তু তার ওপর চলছে একটি ব্যাংকের অনলাইন সেবার VM. বন্ধ করা যাবে না। Live migration-এ VM চলতে চলতেই তার মেমরি, CPU-র অবস্থা আর ডিভাইসের অবস্থা নেটওয়ার্ক দিয়ে আরেকটি যন্ত্রে সরানো হয়; ব্যবহারকারী বড়জোর এক মুহূর্তের থমকানো টের পান। ডিস্ক সাধারণত আগে থেকেই ভাগ করা স্টোরেজে (SAN/NAS, পর্ব ৪০) থাকে, তাই সরাতে হয় মূলত মেমরি। ২০০৩ সালে VMware-এর VMotion আর ২০০৫ সালে Xen-এর গবেষণাপত্র “Live Migration of Virtual Machines” এই পদ্ধতিকে মূলধারায় আনে।
ঢাকায় বাসা বদলের কথা ভাবুন, কিন্তু শর্ত — সংসার একদিনও থামবে না। প্রথম দিন সব আসবাব নতুন বাসায় পাঠালেন, অথচ পুরোনো বাসায় রান্না চলছেই, কিছু হাঁড়ি-পাতিল আবার ব্যবহার হলো। দ্বিতীয় দিন শুধু সেগুলো পাঠালেন — এবার জিনিস অনেক কম। এভাবে কমতে কমতে যখন এক ব্যাগ বাকি, তখন পরিবার এক ঘণ্টার জন্য রান্না বন্ধ রাখল, শেষ ব্যাগ নিয়ে নতুন বাসায় উঠল। এটিই pre-copy: আগে বারবার কপি, শেষে ছোট্ট একটি বিরতি।
ধাপগুলো: (১) গন্তব্যে একটি খালি VM তৈরি, (২) উৎসে dirty page-এর হিসাব রাখা শুরু (EPT-র dirty bit বা লেখা-নিষেধ করে), (৩) প্রথম রাউন্ডে পুরো মেমরি পাঠানো, (৪) প্রতি রাউন্ডে শুধু আগের রাউন্ডে বদলানো page পাঠানো, (৫) বাকি অংশ যথেষ্ট ছোট হলে stop-and-copy: VM থামিয়ে বাকি page আর CPU/ডিভাইসের অবস্থা পাঠানো, (৬) গন্তব্যে VM চালু, নেটওয়ার্কে ঘোষণা যে ঠিকানাটি এখন নতুন যন্ত্রে। থামা থেকে চালু পর্যন্ত সময়টি downtime.
হিসাব — কখন শেষ হবে
ধরুন মেমরি M, নেটওয়ার্কের গতি B, আর VM প্রতি সেকেন্ডে D পরিমাণ নতুন মেমরি “নোংরা” করে। প্রথম রাউন্ডে M পাঠাতে লাগে M/B সেকেন্ড, সেই সময়ে নোংরা হয় D × M/B. তাই প্রতিটি রাউন্ডের পরিমাণ আগেরটির r = D/B গুণ। r < 1 হলে পরিমাণ গুণোত্তর ধারায় কমে; মোট পাঠানো ডেটা প্রায় M/(1 − r), মোট সময় প্রায় M/(B − D). r ≥ 1 হলে কখনো কমবে না — dirty rate নেটওয়ার্কের গতির চেয়ে কম না হলে pre-copy শেষ হয় না. একটি পূর্ণ উদাহরণ: M = ৪০০০ MB (প্রায় ৪ GB), B = ১০০০ MB/s (মোটামুটি ১০ Gbit/s লিংক), D = ২০০ MB/s, আর ৫০ MB-এর নিচে নামলে থামানো হবে।
1 round 0: send all 4000 MB (VM keeps running)2 round 1: send pages dirtied in round 03 round 2: send pages dirtied in round 14 left ≤ 50 MB → pause VM, stop-and-copy5 resume on destination, announce new location
| এই রাউন্ডে পাঠানো | |
| রাউন্ডের সময় | |
| এর মধ্যে নোংরা হলো | |
| মোট পাঠানো | |
| VM কোথায় চলছে |
- রাউন্ড ০ — পুরো মেমরি। ৪০০০ MB ÷ ১০০০ MB/s = ৪ সেকেন্ড। VM পুরো সময় উৎসে চলছে, ব্যবহারকারী কিছু টের পান না। এই ৪ সেকেন্ডে VM লিখে নোংরা করল ২০০ × ৪ = ৮০০ MB — সেগুলোর পাঠানো কপি এখন পুরোনো।
- রাউন্ড ১ — শুধু বদলানো page. ৮০০ MB পাঠাতে ০.৮ সেকেন্ড, এর মধ্যে নতুন নোংরা ২০০ × ০.৮ = ১৬০ MB. খেয়াল করুন, প্রতি রাউন্ডে পরিমাণ r = ২০০/১০০০ = ০.২ গুণ হচ্ছে।
- রাউন্ড ২। ১৬০ MB, ০.১৬ সেকেন্ড, নোংরা ৩২ MB. মোট পাঠানো এখন ৪৯৬০ MB. বাকি ৩২ MB সীমা ৫০ MB-এর নিচে — আর রাউন্ড চালিয়ে লাভ সামান্য।
- Stop-and-copy — একমাত্র বিরতি। VM থামানো হলো, বাকি ৩২ MB আর vCPU-র register ও ডিভাইসের অবস্থা পাঠানো হলো: ৩২ ÷ ১০০০ = ০.০৩২ সেকেন্ড = ৩২ ms downtime (অবস্থার ছোট অংশটুকু বাদ দিয়ে হিসাব)। মোট পাঠানো ৪৯৯২ MB — মেমরির প্রায় ১.২৫ গুণ, যা সূত্র M/(1 − r) = ৪০০০/০.৮ = ৫০০০-এর কাছাকাছি।
- গন্তব্যে চালু। VM নতুন যন্ত্রে ঠিক যেখানে থেমেছিল সেখান থেকে চলে। Hypervisor নেটওয়ার্কে একটি ঘোষণা-প্যাকেট (যেমন gratuitous ARP বা RARP) পাঠায়, যাতে switch-গুলো জানে ঠিকানাটি এখন কোন পোর্টে। মোট সময় ৪.৯৯২ সেকেন্ড, যার মাত্র ৩২ ms-এ সেবা থেমেছিল। উৎসের মেমরি এবার মুক্ত।
এবার একই হিসাব একটি calculator-এ, তিনটি ভিন্ন dirty rate দিয়ে। শর্ত: বাকি ৫০ MB-এর নিচে নামলে বা ৬টি রাউন্ড হয়ে গেলে থামানো হবে, আর এক রাউন্ডে মোট মেমরির বেশি নোংরা হতে পারে না।
// Pre-copy live migration: copy all memory, then re-copy what got dirty, until small enough
function migrate(memMB, dirtyMBps, bwMBps, stopMB = 50, maxRounds = 6) {
console.log(`--- memory ${memMB} MB, dirty ${dirtyMBps} MB/s, link ${bwMBps} MB/s ---`);
let toSend = memMB, total = 0, time = 0, round = 0;
while (toSend > stopMB && round < maxRounds) {
const t = toSend / bwMBps; // seconds this round takes
const dirtied = Math.min(memMB, dirtyMBps * t); // pages written meanwhile (max = all memory)
console.log(`round ${round}: send ${toSend.toFixed(1).padStart(7)} MB in ${t.toFixed(3)} s,` +
` dirtied meanwhile ${dirtied.toFixed(1)} MB`);
total += toSend; time += t; toSend = dirtied; round++;
}
const down = toSend / bwMBps; // stop-and-copy: the VM is paused
total += toSend; time += down;
console.log(`stop-and-copy: pause VM, send ${toSend.toFixed(1)} MB -> downtime ${(down * 1000).toFixed(0)} ms`);
console.log(`total sent ${total.toFixed(1)} MB (${(total / memMB).toFixed(2)}x memory), total time ${time.toFixed(3)} s` +
(round === maxRounds ? " [round limit hit before reaching " + stopMB + " MB]" : ""));
}
migrate(4000, 200, 1000); // dirty rate is 20% of bandwidth -> converges fast
migrate(4000, 1200, 1000); // writes faster than the link -> never converges
migrate(4000, 600, 1000); // 60%: shrinks slowly -> round limit, longer pauseআসল আউটপুট:
--- memory 4000 MB, dirty 200 MB/s, link 1000 MB/s ---
round 0: send 4000.0 MB in 4.000 s, dirtied meanwhile 800.0 MB
round 1: send 800.0 MB in 0.800 s, dirtied meanwhile 160.0 MB
round 2: send 160.0 MB in 0.160 s, dirtied meanwhile 32.0 MB
stop-and-copy: pause VM, send 32.0 MB -> downtime 32 ms
total sent 4992.0 MB (1.25x memory), total time 4.992 s
--- memory 4000 MB, dirty 1200 MB/s, link 1000 MB/s ---
round 0: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
round 1: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
round 2: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
round 3: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
round 4: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
round 5: send 4000.0 MB in 4.000 s, dirtied meanwhile 4000.0 MB
stop-and-copy: pause VM, send 4000.0 MB -> downtime 4000 ms
total sent 28000.0 MB (7.00x memory), total time 28.000 s [round limit hit before reaching 50 MB]
--- memory 4000 MB, dirty 600 MB/s, link 1000 MB/s ---
round 0: send 4000.0 MB in 4.000 s, dirtied meanwhile 2400.0 MB
round 1: send 2400.0 MB in 2.400 s, dirtied meanwhile 1440.0 MB
round 2: send 1440.0 MB in 1.440 s, dirtied meanwhile 864.0 MB
round 3: send 864.0 MB in 0.864 s, dirtied meanwhile 518.4 MB
round 4: send 518.4 MB in 0.518 s, dirtied meanwhile 311.0 MB
round 5: send 311.0 MB in 0.311 s, dirtied meanwhile 186.6 MB
stop-and-copy: pause VM, send 186.6 MB -> downtime 187 ms
total sent 9720.1 MB (2.43x memory), total time 9.720 s [round limit hit before reaching 50 MB]
প্রথম ক্ষেত্রটি ওপরের stepper-এর হুবহু মিল: ৩ রাউন্ড, ৩২ ms downtime. দ্বিতীয় ক্ষেত্রে VM লেখে ১২০০ MB/s, লিংক বয় ১০০০ MB/s — r = ১.২, প্রতি রাউন্ডে পুরো ৪০০০ MB আবার নোংরা। ৬ রাউন্ড পরে জোর করে থামাতে হলো: ৪ সেকেন্ড downtime আর মেমরির ৭ গুণ ডেটা নেটওয়ার্কে — সবচেয়ে খারাপ ফল। তৃতীয় ক্ষেত্রে r = ০.৬: পরিমাণ কমছে, কিন্তু ধীরে; রাউন্ড শেষ হওয়ার আগে ৫০ MB-এ নামেনি, তাই ১৮৭ ms downtime. বাস্তবের hypervisor এই অবস্থায় কিছু কৌশল নেয়: auto-converge (VM-এর vCPU কিছুক্ষণ ধীর করে D কমানো), পাঠানোর আগে compression, বা post-copy — আগে CPU-র অবস্থা পাঠিয়ে গন্তব্যে চালু করা, তারপর page লাগলে উৎস থেকে চেয়ে আনা (downtime কম, কিন্তু মাঝপথে নেটওয়ার্ক গেলে VM হারানোর ঝুঁকি)। আর বাস্তবে নোংরা হওয়া মেমরি সাধারণত পুরো মেমরি নয়, VM-এর “লেখার working set”-এ সীমিত — পর্ব ৩৭-এর working set-এরই আরেক রূপ।
৯ · Nested virtualization আর VM-এর নিরাপত্তা
VM-এর ভেতরে VM. Nested virtualization-এ একটি guest নিজেই hypervisor চালায় — যেমন cloud-এর VM-এ Android emulator বা অন্য VM চালিয়ে পরীক্ষা, বা Windows-এর VBS চালু থাকা একটি Windows guest. VT-x-এ “VM-এর ভেতরে VMX” সরাসরি নেই, তাই নিচের hypervisor (L0) ভেতরের hypervisor-এর (L1) প্রতিটি VMX instruction ধরে অনুকরণ করে, আর L1-এর VMCS-কে নিজের একটি VMCS-এ মিলিয়ে L2-কে চালায় — IBM-এর “Turtles” প্রকল্পের (২০১০) কাজ এর ভিত্তি। প্রতিটি L2 exit অনেকগুলো L1 exit-এ পরিণত হতে পারে, তাই খরচ বেশি; নতুন CPU-তে VMCS shadowing-এর মতো সহায়তা এই খরচ কমায়। আমাদের কোড-সার্ভারে vmx/svm না থাকার মানে এই সুবিধা সেখানে বন্ধ।
Isolation কতটা শক্ত? VM-এর সীমানা container-এর সীমানার চেয়ে মোটা, কারণ আক্রমণকারীকে guest-এর kernel পেরিয়েও hypervisor-এর ছোট interface (exit-এর ধরন, hypercall, অনুকরণ করা ডিভাইস) ভাঙতে হয়। তবু সীমানা অভেদ্য নয়। VM escape মানে guest-এর ভেতর থেকে hypervisor বা host-এ কোড চালাতে পারা — cloud-এর সবচেয়ে গুরুতর ঘটনা, কারণ একটি যন্ত্রে অনেক গ্রাহক। একটি পরিচিত উদাহরণ ২০১৫ সালের “VENOM” (CVE-2015-3456): QEMU-র অনুকরণ করা পুরোনো floppy-ডিস্ক controller-এর একটি buffer overflow, যা অনেক VM-এ ব্যবহার না হলেও ডিফল্টভাবে উপস্থিত ছিল। শিক্ষা আক্রমণের কৌশল নয়, প্রতিরক্ষার নকশা:
Side channel. একই CPU, cache আর TLB ভাগ করা মানে এক VM অন্য VM-এর কাজের সূক্ষ্ম পার্শ্বপ্রতিক্রিয়া মাপতে পারে — side channel. ২০১৮ সালের Spectre, Meltdown আর বিশেষ করে L1TF (“Foreshadow”) cloud-এ গুরুতর ছিল; প্রতিকার হিসেবে hypervisor VM entry-তে L1 cache খালি করে, কোনো কোনো ক্ষেত্রে SMT বন্ধ করা হয়, আর ভিন্ন গ্রাহককে ভিন্ন core দেওয়া হয় (core scheduling). আরেকটি নতুন দিক confidential computing (AMD SEV, Intel TDX): VM-এর মেমরি CPU নিজেই এনক্রিপ্ট করে, যাতে hypervisor বা cloud-এর কর্মীরাও তা পড়তে না পারেন — হুমকির মডেল উল্টে যায়, hypervisor-ও তখন “অবিশ্বস্ত”।
আরও গভীরে: Linux KVM-এর কোড মূলত virt/kvm/ (সব architecture-এর অংশ) আর arch/x86/kvm/-এ; সেখানে vmx/ আর svm/ ফোল্ডারে Intel ও AMD-র আলাদা অংশ, আর mmu/-তে EPT/NPT-র “TDP MMU”. ARM-এ hypervisor-এর জন্য আলাদা একটি exception level আছে (EL2), আর ARMv8.1-এর VHE সুবিধায় পুরো host kernel EL2-তে চলতে পারে — KVM-এর “type 1 না type 2” তর্কটি ARM-এ আরও ঝাপসা। আধুনিক cloud-এ আরেকটি দিক “exit-less” নকশা: posted interrupt দিয়ে ডিভাইসের interrupt VM exit ছাড়াই guest-এ পৌঁছায়, আর vhost/vDPA-তে virtio-র ডেটাপথ QEMU-কে এড়িয়ে kernel বা হার্ডওয়্যারে চলে।
পরীক্ষা ও ইন্টারভিউতে এই বিষয়ে প্রায়ই যা জিজ্ঞেস করা হয়:
- Popek–Goldberg-এর শর্ত কী? — equivalence, resource control, efficiency; আর উপপাদ্য: sensitive instruction ⊆ privileged instruction হলে trap-and-emulate দিয়ে VMM বানানো যায়।
- Type 1 আর type 2 hypervisor-এর পার্থক্য? — type 1 সরাসরি হার্ডওয়্যারে (ESXi, Xen, Hyper-V); type 2 একটি host OS-এর ওপর অ্যাপ হিসেবে (VirtualBox, VMware Workstation); KVM-কে দুই দলেই ফেলার যুক্তি আছে।
- Full virtualization আর paravirtualization-এর পার্থক্য? — full-এ guest অপরিবর্তিত (binary translation বা VT-x); para-তে guest বদলানো, সে hypercall দিয়ে hypervisor-কে ডাকে।
- EPT-তে ৪ × ৪ স্তরে TLB miss-এ সবচেয়ে বেশি কত মেমরি-পড়া? — walk-এ (৪ + ১)(৪ + ১) − ১ = ২৪, ডেটাসহ ২৫.
- Pre-copy live migration কখন শেষ হয় না? — dirty rate নেটওয়ার্কের গতির সমান বা বেশি হলে; তখন auto-converge, compression বা post-copy লাগে।
১০ · AI-এর যুগে virtualization-এর কাজ
VM বানানো, KVM সেটআপ, “VT-x is disabled” error — এসব প্রশ্নে AI দ্রুত উত্তর দেয়। কিন্তু AI জানে না আপনার CPU Intel না AMD, আপনি Windows-এ Hyper-V চালু রেখেছেন কি না, বা আপনি নিজেই একটি cloud VM-এর ভেতরে কি না। তাই উত্তরগুলো প্রায়ই “ঠিক, কিন্তু ভুল যন্ত্রের জন্য”।
| AI-এর সাধারণ পরামর্শ | সমস্যা | ভালো পথ |
|---|---|---|
“vmx নেই, তাই আপনার CPU virtualization সমর্থন করে না” | হয়তো আপনি নিজেই VM-এর ভেতরে (nested বন্ধ), বা AMD CPU (svm খুঁজতে হবে), বা BIOS/UEFI-তে বন্ধ | আগে hypervisor flag আর CPU-র নির্মাতা দেখুন; BIOS/UEFI-র সেটিং যাচাই করুন |
sudo modprobe kvm_intel — AMD যন্ত্রেও | ভুল module; error-এর মানে বোঝা যায় না | AMD-তে kvm_amd; lsmod | grep kvm দিয়ে যাচাই |
sudo chmod 666 /dev/kvm | যন্ত্রের সব ব্যবহারকারীকে hypervisor-এর দরজা খুলে দেওয়া | নিজেকে kvm group-এ যোগ করুন (পর্ব ৪৭), তারপর আবার লগইন |
| “VirtualBox চালাতে Hyper-V আর memory integrity বন্ধ করুন” | Windows-এর VBS-নির্ভর নিরাপত্তা বন্ধ হয়ে যায়; প্রায়ই অপ্রয়োজনীয় | নতুন VirtualBox/VMware Hyper-V-র ওপরও চলে; বন্ধ করলে কী হারাচ্ছেন জেনে সিদ্ধান্ত নিন |
| EPT walk-এর খরচ “৮” বা “১৬”, migration-এর downtime “শূন্য” | সংখ্যাগুলো আন্দাজ, হিসাব নয় | (n + 1)(m + 1) − 1 আর M, D, B দিয়ে নিজে হিসাব করুন |
AI-কে প্রশ্ন করার সময় নিজের পরিবেশটি পুরোপুরি বলে দিন, আর যাচাইয়ের কমান্ড চেয়ে নিন:
AI-এর virtualization-পরামর্শ যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন।
প্র ০১x86 তো Popek–Goldberg-এর শর্ত ভাঙত — তবু VMware ১৯৯৯ সালেই কীভাবে দ্রুত VM চালাল? আর প্রথম প্রজন্মের VT-x কেন সবসময় দ্রুততর ছিল না?
উপপাদ্যটি বলে sensitive ⊆ privileged হলে trap-and-emulate যথেষ্ট; এটি বলে না যে অন্য কোনো পথে VMM বানানো অসম্ভব। VMware অন্য পথ নিয়েছিল। Guest-এর user-স্তরের কোড সাধারণত সমস্যাহীন, তাই সেটি সরাসরি CPU-তে চলত। Guest kernel-এর কোড চালানোর আগে VMM সেটিকে ছোট ছোট খণ্ডে পড়ত, POPF বা SGDT-র মতো সমস্যাজনক instruction-কে নিরাপদ কোডে বদলে দিত, আর অনুবাদ-করা খণ্ড একটি cache-এ রাখত। প্রায় সব কোড একবার অনুবাদের পর বারবার চলে, তাই খরচ ভাগ হয়ে যেত। এই binary translation আর direct execution-এর মিশ্রণই প্রমাণ করে যে hardware-এর ঘাটতি software দিয়ে পূরণ করা যায় — দামটা ছিল একটি অত্যন্ত জটিল VMM.
২০০৫–০৬ সালে VT-x আর AMD-V এলো, কিন্তু ২০০৬ সালে VMware-এর Keith Adams আর Ole Agesen-এর একটি তুলনামূলক গবেষণায় দেখা গেল, অনেক কাজে প্রথম প্রজন্মের hardware সহায়তা binary translation-এর চেয়ে ধীর. কারণ: প্রতিটি VM exit/entry তখন খুব দামি ছিল, আর মেমরির জন্য তখনও shadow page table লাগত — guest page table বদলালেই exit. প্রসেস তৈরি, context switch, page fault-এর মতো কাজে exit-এর বন্যা হতো। অন্যদিকে binary translator চতুরভাবে অনেক কাজ exit ছাড়াই সারতে পারত।
পরের কয়েক প্রজন্মে exit-এর খরচ কমল, EPT/NPT এলো, VPID/ASID-এ TLB খালি করা লাগল না, posted interrupt-এ interrupt-এর exit-ও কমল। তখন hardware সহায়তা স্পষ্টভাবে জিতে যায়, আর VMware-ও ধীরে ধীরে binary translation ছেড়ে দেয়। এর শিক্ষা কম্পিউটার বিজ্ঞানের একটি পুনরাবৃত্ত গল্প: নতুন hardware বৈশিষ্ট্য প্রথমে পুরোনো চতুর software-এর সাথে পাল্লা দিতে পারে না; কয়েক প্রজন্মের পরিশোধনের পর জেতে। পর্ব ৩৩-এ hardware বনাম software TLB-র গল্পেও একই ধাঁচ দেখেছেন।
মূল উপলব্ধি: একটি তাত্ত্বিক শর্ত “যথেষ্ট” শর্ত দেয়, “প্রয়োজনীয়” নয়; আর কোনো সমাধান কতটা ভালো, তা নির্ভর করে প্রকৃত খরচের অনুপাতের ওপর — exit কত দামি, page table কত ঘন ঘন বদলায় — যা প্রতি প্রজন্মে বদলায়।
প্র ০২KVM কি type 1 না type 2 hypervisor? প্রশ্নটি কি আদৌ গুরুত্বপূর্ণ?
Type 1 আর type 2-এর ভাগটি এসেছে ১৯৭০-এর দশকের Goldberg-এর কাজ থেকে, যখন hypervisor হয় খালি হার্ডওয়্যারে বসত, নয়তো একটি OS-এর ওপর চলত। KVM এই দুই ছকের কোনোটিতেই পুরোপুরি মেলে না। এক দিকে, KVM module লোড হলে Linux kernel নিজেই VMX root mode-এ বসে hardware-কে সরাসরি নিয়ন্ত্রণ করে; ESXi বা Hyper-V-র মতো এর নিচে আর কোনো OS নেই — এই যুক্তিতে Red Hat-এর মতো অনেকে একে type 1 বলেন। অন্য দিকে, host-এ একটি পূর্ণ সাধারণ OS চলছে — desktop, ব্রাউজার, compiler সবই চালানো যায় — আর প্রতিটি VM হলো একটি সাধারণ QEMU প্রসেস, যার vCPU thread-কে Linux-এর CFS/EEVDF scheduler (পর্ব ২১) অন্য thread-এর মতোই পালা দেয়। এই চোখে KVM দেখতে type 2-এর মতো।
Hyper-V-ও একই রকম ঝাপসা: Windows চালু থাকে, কিন্তু সে আসলে hypervisor-এর ওপর একটি root partition. Xen-এ hypervisor ছোট, কিন্তু ডিভাইস driver থাকে dom0 নামের একটি Linux VM-এ। ARM-এ VHE এসে KVM-এর host kernel সরাসরি hypervisor-এর exception level-এ চলে।
তাহলে কোন প্রশ্নগুলো আসলে কাজের? (১) Trusted computing base কত বড় — সবচেয়ে বেশি ক্ষমতায় কত লাইনের কোড চলে? ESXi বা Xen-এর ছোট hypervisor বনাম পুরো Linux kernel — নিরাপত্তার জন্য এই হিসাব গুরুত্বপূর্ণ। (২) ডিভাইস driver কোথায় — hypervisor-এ, host OS-এ, না আলাদা VM-এ? (৩) Scheduling আর মেমরি কে সামলায় — hypervisor-এর নিজস্ব scheduler, না host OS-এরটা? KVM-এর বড় সুবিধা এখানেই: Linux-এর পরিণত scheduler, মেমরি-ব্যবস্থাপনা (KSM, THP, NUMA), driver আর cgroup সব বিনামূল্যে পাওয়া যায়।
মূল উপলব্ধি: শ্রেণিবিভাগ শেখার জন্য উপকারী, কিন্তু নকশা বোঝার জন্য প্রশ্ন করতে হয় — কোন কোড কোন privilege-এ চলে, কে driver আর scheduler সামলায়, আর বিশ্বাসের ভিত কতটা বড়।
প্র ০৩EPT-র walk-এ ২৪টি পড়া লাগে, shadow page table-এ মাত্র ৪টি। তবু আজ প্রায় সবাই EPT/NPT কেন ব্যবহার করে?
সংখ্যা দুটি একই জিনিস মাপে না। Shadow page table-এ TLB miss সস্তা, কারণ CPU সরাসরি gVA → hPA-র একটি সাধারণ চার স্তরের টেবিল হাঁটে। কিন্তু সেই টেবিল বানিয়ে রাখার খরচ লুকানো থাকে অন্যত্র: guest-এর প্রতিটি page table পাতা লেখা-নিষেধ, তাই guest নতুন mapping বসালে, প্রসেস fork করলে (পর্ব ১০-এর copy-on-write-এ অনেক PTE বদলায়), বা context switch-এ CR3 বদলালে — প্রতিবার VM exit, আর hypervisor-কে ছায়াটি মেলাতে হয়। প্রতিটি guest প্রসেসের জন্য আলাদা ছায়া রাখতে হয়, মেমরিও খরচ হয়। Web সার্ভার, compiler বা database-এর মতো কাজে, যেখানে প্রসেস আর mapping ঘন ঘন বদলায়, এই exit-এর বন্যাই প্রধান খরচ।
EPT/NPT-তে guest নিজের টেবিল যত খুশি বদলায়, hypervisor জড়ায় না। খরচ সরে যায় TLB miss-এ — সবচেয়ে খারাপ ক্ষেত্রে ২৪টি পড়া। কিন্তু বাস্তবে সেই সবচেয়ে খারাপ অবস্থা বিরল: TLB-র hit rate সাধারণত খুব বেশি, CPU-র paging-structure cache আর আলাদা nested-TLB মাঝের অনুবাদ মনে রাখে, আর পড়াগুলোর বেশিরভাগ যায় L1/L2 cache-এ, RAM-এ নয়। Host-এ 2 MiB বা 1 GiB huge page ব্যবহার করলে host-এর স্তর কমে, সূত্রে m ছোট হয় — (৪ + ১)(৩ + ১) − ১ = ১৯, বা আরও কম।
আরেকটি সুবিধা সরলতা। Shadow paging-এর কোড hypervisor-এর সবচেয়ে জটিল, বাগপ্রবণ অংশগুলোর একটি ছিল; EPT তা অনেকটা সরিয়ে দেয়, আর live migration-এর dirty-page হিসাবও hardware-এর dirty bit দিয়ে সহজ হয়। তবে shadow-এর চিন্তা হারায়নি: nested virtualization-এ L0 hypervisor প্রায়ই L1-এর EPT-র একটি “shadow EPT” রাখে — পুরোনো কৌশল নতুন স্তরে।
মূল উপলব্ধি: কোনো একটি অপারেশনের সবচেয়ে খারাপ খরচ দিয়ে নকশা বিচার করা যায় না; দেখতে হয় কোন ঘটনা কত ঘন ঘন ঘটে। EPT দুর্লভ ঘটনাকে (TLB miss) দামি করে ঘন ঘন ঘটনাকে (page table বদল) সস্তা করেছে।
প্র ০৪VM-এর isolation যদি এত শক্ত হয়, তাহলে cloud কোম্পানিগুলো hypervisor-কে ছোট করা আর QEMU-কে sandbox-এ রাখা নিয়ে এত চিন্তিত কেন?
Cloud-এ একটি ভৌত যন্ত্রে অচেনা অনেক গ্রাহকের VM পাশাপাশি চলে। তাদের মধ্যে কেউ ইচ্ছাকৃতভাবে আক্রমণকারী হতে পারে — তার নিজের VM-এ পুরো root অধিকার আছে, যা খুশি কোড চালাতে পারে। তাই হুমকির মডেল হলো: “guest kernel-টি নিজেই শত্রু।” তখন নিরাপত্তা নির্ভর করে guest যে interface দিয়ে hypervisor-এর সাথে কথা বলে, তার প্রতিটি লাইনের সঠিকতার ওপর — exit handler, hypercall, আর বিশেষত অনুকরণ করা ডিভাইস।
অনুকরণ করা ডিভাইসগুলোই ঐতিহাসিকভাবে দুর্বলতম জায়গা। কারণ সেগুলো পুরোনো হার্ডওয়্যারের জটিল আচরণ নকল করে, অনেক কোড, আর guest ইচ্ছেমতো অদ্ভুত register-মান পাঠাতে পারে। ২০১৫ সালের VENOM দুর্বলতা ছিল QEMU-র virtual floppy controller-এ — এমন একটি ডিভাইস যা প্রায় কেউ ব্যবহার করত না, কিন্তু ডিফল্টভাবে উপস্থিত ছিল। এর প্রতিরক্ষামূলক শিক্ষা তিনটি: (১) attack surface ছোট রাখা — অপ্রয়োজনীয় ডিভাইস বাদ, কম কোডের VMM (Firecracker-এর মতো microVM-এ খুব অল্প ডিভাইস — পর্ব ৫২); (২) defense in depth — QEMU-কে আলাদা unprivileged user, seccomp আর SELinux-এর sVirt label-এ রাখা, যাতে একটি VM-এর QEMU ভাঙলেও অন্য VM-এর ডিস্ক বা host-এর ফাইলে হাত না পড়ে; (৩) গুরুত্বপূর্ণ কাজ মূল CPU থেকে সরিয়ে আলাদা হার্ডওয়্যারে নেওয়া — AWS Nitro-র মতো নকশার একটি উদ্দেশ্য এটাই।
এর ওপর আছে side channel, যা কোনো software-বাগ ছাড়াই ভাগ করা হার্ডওয়্যার থেকে তথ্য ফাঁস করে — ২০১৮-র L1TF-এর পর বহু cloud core scheduling আর VM entry-তে cache খালি করা চালু করে। আর confidential computing এখন প্রশ্নটি উল্টে দিচ্ছে: গ্রাহক cloud-এর hypervisor-কেও বিশ্বাস করতে চান না।
মূল উপলব্ধি: শক্ত সীমানা মানে অভেদ্য সীমানা নয়; নিরাপত্তা আসে স্তরে স্তরে — ছোট interface, কম ক্ষমতা, দ্রুত হালনাগাদ — ধরে নিয়ে যে কোনো একটি স্তর একদিন ভাঙবে।
প্র ০৫Live migration শুধু মেমরি কপির ব্যাপার নয় — নেটওয়ার্ক, ডিস্ক আর CPU-র দিক থেকে আর কী কী সমস্যা সমাধান করতে হয়?
মেমরির রাউন্ডগুলো হিসাবের সবচেয়ে সুন্দর অংশ, কিন্তু বাস্তবে migration সফল হতে আরও কয়েকটি শর্ত পূরণ করতে হয়। ডিস্ক: VM-এর ডিস্ক যদি উৎস যন্ত্রের লোকাল ডিস্কে থাকে, তাকেও সরাতে হবে — সেটি মেমরির চেয়ে বহুগুণ বড়। তাই ডেটা সেন্টারে VM-এর ডিস্ক সাধারণত ভাগ করা স্টোরেজে (SAN, NAS, বা Ceph-এর মতো distributed storage) রাখা হয়; না থাকলে block migration লাগে, যা ঘণ্টা ধরে চলতে পারে।
নেটওয়ার্ক: VM-এর IP আর MAC ঠিকানা একই থাকে, কিন্তু সে এখন অন্য ভৌত পোর্টে। তাই নতুন host একটি ঘোষণা-প্যাকেট (gratuitous ARP বা RARP) পাঠায়, যাতে switch-গুলো টেবিল হালনাগাদ করে। দুই host একই layer-2 নেটওয়ার্কে না থাকলে overlay নেটওয়ার্ক লাগে। চলমান TCP সংযোগ টিকে থাকে, কারণ downtime TCP-র retransmit-এর সময়ের চেয়ে ছোট।
CPU-র সামঞ্জস্য: guest চালুর সময় CPUID দেখে ঠিক করেছে AVX-512-এর মতো কোন instruction ব্যবহার করবে। গন্তব্যের CPU পুরোনো হলে সেই instruction-এ guest crash করবে। তাই cluster-এ সব host-এর “সাধারণ লঘিষ্ঠ” CPU মডেল guest-কে দেখানো হয় (VMware-এর EVC, QEMU-র নামযুক্ত CPU মডেল)। Passthrough বা SR-IOV ডিভাইস থাকলে migration প্রায় অসম্ভব, কারণ হার্ডওয়্যারের অবস্থা কপি করা যায় না। আর নিরাপত্তা: migration-এর স্রোতে VM-এর পুরো মেমরি — পাসওয়ার্ড, key — যায়, তাই এটি এনক্রিপ্টেড বা আলাদা নেটওয়ার্কে পাঠাতে হয়।
এত ঝামেলার পরও এটি অমূল্য। Google প্রকাশ্যে জানিয়েছে যে তাদের Compute Engine হার্ডওয়্যার বা software রক্ষণাবেক্ষণের সময় গ্রাহকের VM live migrate করে, যাতে গ্রাহককে VM বন্ধ করতে না হয়। অর্থাৎ যন্ত্রের রক্ষণাবেক্ষণ আর গ্রাহকের সেবা — দুটি আলাদা হয়ে যায়।
মূল উপলব্ধি: একটি চলন্ত সিস্টেমকে সরানো মানে তার সব নির্ভরতা — ডিস্ক, নেটওয়ার্ক-পরিচয়, CPU-র বৈশিষ্ট্য, গোপন তথ্য — একসাথে সরানো; মেমরির গুণোত্তর ধারা শুধু শুরুর অংশ।
অনুশীলন
হাতে হিসাব, ফল আগে থেকে বলা, আর নিজের যন্ত্রে যাচাই।
-
Walk-এর হিসাব: একটি VM-এ guest চার স্তরের page table ব্যবহার করে। TLB আর সব cache খালি ধরে একটি TLB miss-এ মোট কতবার মেমরি ছুঁতে হবে (ডেটাসহ), যদি (ক) host-ও চার স্তর ব্যবহার করে, (খ) host 2 MiB page দিয়ে তিন স্তর ব্যবহার করে, (গ) VM ছাড়া সাধারণ প্রসেসে?
সূত্র: walk-এর পড়া = (n + 1)(m + 1) − 1, তারপর ডেটার জন্য আরও ১। (ক) n = ৪, m = ৪: (৫)(৫) − ১ = ২৪, ডেটাসহ ২৫. (খ) n = ৪, m = ৩: (৫)(৪) − ১ = ১৯, ডেটাসহ ২০. (গ) সাধারণ চার স্তর: ৪ + ১ = ৫. অর্থাৎ host-এ huge page দিলেই সবচেয়ে খারাপ ক্ষেত্রে ২৫ থেকে ২০-এ নামে।
-
Migration-এর হিসাব: একটি VM-এর মেমরি ৮০০০ MB, লিংক ১২৫০ MB/s, dirty rate ২৫০ MB/s; বাকি ১০০ MB-এর নিচে নামলে stop-and-copy. প্রতিটি রাউন্ডে কত পাঠানো হবে, downtime কত, মোট ডেটা ও মোট সময় কত?
r = ২৫০/১২৫০ = ০.২. রাউন্ড ০: ৮০০০ MB, ৬.৪ s, নোংরা ১৬০০ MB. রাউন্ড ১: ১৬০০ MB, ১.২৮ s, নোংরা ৩২০ MB. রাউন্ড ২: ৩২০ MB, ০.২৫৬ s, নোংরা ৬৪ MB. ৬৪ < ১০০, তাই stop-and-copy: ৬৪ ÷ ১২৫০ = ০.০৫১২ s = ৫১.২ ms downtime. মোট ডেটা ৮০০০ + ১৬০০ + ৩২০ + ৬৪ = ৯৯৮৪ MB, মোট সময় ৬.৪ + ১.২৮ + ০.২৫৬ + ০.০৫১২ = ৭.৯৮৭২ s. মিলিয়ে দেখুন: M/(B − D) = ৮০০০/১০০০ = ৮ s — কাছাকাছি। চাইলে ওপরের calculator-এ
migrate(8000, 250, 1250, 100)যোগ করে যাচাই করুন। -
আগে থেকে বলুন: ওপরের
cpuid_hv.cপ্রোগ্রামটি (ক) Windows ছাড়া শুধু Linux চলা একটি পুরোনো ডেস্কটপে (কোনো hypervisor নেই), আর (খ) VirtualBox-এর ভেতরের একটি Ubuntu-তে চালালে প্রথম লাইনে কী আসবে? আর খেলনা VMM-এ যদি guest-এর তালিকায়["popf", 1]-এর জায়গায়["sti"]থাকত, দ্বিতীয় চালানোর শেষ লাইন কী হতো?(ক)
leaf 1 ECX bit 31 (hypervisor present): 0, আর পরে “hypervisor: not found …” — bare metal-এ CPU এই bit বসায় না (যদি না hypervisor চলছে)। (খ) bit ৩১ = ১. Leaf 0x40000000-এর নাম নির্ভর করে VirtualBox-এর paravirtualization সেটিংয়ের ওপর — Linux guest-এ ডিফল্টভাবে সাধারণত KVM-এর interface দেখায় (“KVMKVMKVM”), “Minimal” সেটিংয়ে “VBoxVBoxVBox”. অর্থাৎ নাম দেখে hypervisor চেনা সবসময় নির্ভরযোগ্য নয় — চালিয়ে দেখাই ভালো। খেলনা VMM: STI privileged, তাই দুই চালানোতেই trap হবে; VMM IF = 1 বসাবে। কিন্তু খেয়াল করুন, simulator-এর কোডেsti-র শাখা নেই —whatথাকবে undefined আর IF বদলাবে না; শেষ লাইন হবেexits=6 final IF=0 (bare metal: 1) equivalent? NO. অর্থাৎ trap ঠিকই হলো, কিন্তু অনুকরণ ভুল — VMM-এর বাগও equivalence ভাঙে। একটি লাইন যোগ করে ঠিক করুন:if (op === "sti") { v.IF = 1; what = "IF=1"; }. -
নিজের যন্ত্রে কমান্ড: আপনার Linux ল্যাপটপে KVM চালানো যাবে কি না যাচাইয়ের জন্য ৪–৫টি কমান্ডের একটি ছোট তালিকা লিখুন — কোনোটিতে sudo বা অনুমতি বদলানো ছাড়া। প্রতিটি কী প্রমাণ করে, তাও লিখুন।
একটি সম্ভাব্য তালিকা:
grep -c -E 'vmx|svm' /proc/cpuinfo— ০-এর বেশি হলে CPU (আর BIOS/UEFI) hardware virtualization দেখাচ্ছে; Intel-এ vmx, AMD-তে svm.grep -m1 -o -w hypervisor /proc/cpuinfo— কিছু ছাপলে আপনি নিজেই VM-এর ভেতরে; তখন nested virtualization লাগবে।lsmod | grep kvm—kvmআরkvm_intelবাkvm_amdলোড হয়েছে কি না।ls -l /dev/kvm— ফাইলটি আছে কি না আর তার group (সাধারণতkvm).id -nG— আপনিkvmgroup-এ আছেন কি না; না থাকলে admin-কে group-এ যোগ করতে বলুন (chmod নয়)। অনেক distro-তেvirt-host-validate-ও এক জায়গায় এসব যাচাই করে।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমVT-x-এ guest একটি I/O instruction চালালে যা ঘটে, সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 🖥️ Guest non-root mode-এ
outinstruction চালায় - 🚪 CPU guest-এর অবস্থা আর exit reason VMCS-এ রেখে hypervisor-এ ফেরে
- 🛠️ Hypervisor exit reason পড়ে ডিভাইসটি অনুকরণ করে
- ➡️ Hypervisor guest-এর RIP পরের instruction-এ এগিয়ে দেয়
- ↩️ VMRESUME দিয়ে VM entry — guest আবার চলে
Popek–Goldberg-এর উপপাদ্য অনুযায়ী কোন শর্তে শুধু trap-and-emulate দিয়ে একটি VMM বানানো যায়?
- সব privileged instruction sensitive হলে
- সব sensitive instruction privileged হলে (sensitive ⊆ privileged)
- CPU-তে privileged instruction ১০টির কম হলে
- CPU-তে multilevel page table থাকলে
Intel VT-x-এ “VM exit” বলতে কী বোঝায়?
- VM-টি পুরোপুরি বন্ধ হয়ে যাওয়া
- Guest-এর একটি প্রসেস system call করে guest kernel-এ যাওয়া
- Non-root mode থেকে CPU-র root mode-এ hypervisor-এর কাছে ফেরা, guest-এর অবস্থা VMCS-এ রেখে
- VM-কে এক যন্ত্র থেকে আরেক যন্ত্রে সরানো
EPT/NPT ব্যবহার করা একটি VM-এ guest আর host দুটিই চার স্তরের page table ব্যবহার করে। TLB ও cache খালি থাকলে একটি TLB miss-এ page walk-এর জন্য সবচেয়ে বেশি কতটি মেমরি-পড়া লাগে (ডেটা পড়া বাদে)?
- ৪
- ৮
- ১৬
- ২৪
নিচের কোনটি type 2 (hosted) hypervisor-এর উদাহরণ?
- Oracle VirtualBox
- VMware ESXi
- Xen
- Microsoft Hyper-V
একটি VM-এর মেমরি ৪০০০ MB, migration লিংকের গতি ১০০০ MB/s. Pre-copy live migration কোন ক্ষেত্রে কখনো যথেষ্ট ছোট অবশিষ্টাংশে পৌঁছাবে না?
- VM প্রতি সেকেন্ডে ২০০ MB মেমরি বদলালে
- VM প্রতি সেকেন্ডে ১২০০ MB মেমরি বদলালে
- VM প্রায় অলস থাকলে
- মেমরি ৪০০০ MB-এর বদলে ২০০০ MB হলে
Memory ballooning-এর মূল উদ্দেশ্য কী?
- Guest-এর মেমরি এনক্রিপ্ট করা
- একাধিক VM-এর একই রকম page এক কপিতে রাখা
- Guest-এর ভেতরের একটি driver দিয়ে guest-এর কাছ থেকে মেমরি ফেরত নিয়ে host-কে দেওয়া
- Live migration-এর গতি বাড়ানো
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- Hypervisor একটি যন্ত্রকে অনেক VM-এ ভাগ করে; ভালো VMM-এর তিন শর্ত — equivalence, resource control, efficiency; উপপাদ্য: sensitive ⊆ privileged হলে trap-and-emulate যথেষ্ট।
- পুরোনো x86 শর্ত ভাঙত (POPF, SGDT/SIDT); সমাধান binary translation, paravirtualization (hypercall) আর VT-x/AMD-V — root/non-root mode, VM exit/entry, VMCS.
- Type 1 হার্ডওয়্যারে (ESXi, Xen, Hyper-V), type 2 OS-এর ওপর (VirtualBox, Workstation); KVM দুই দলের মাঝামাঝি; Linux-এ KVM + QEMU,
/dev/kvmআরKVM_RUN-এর লুপ। - মেমরি: shadow page table বনাম EPT/NPT — walk (n + 1)(m + 1) − 1 = ২৪; I/O: অনুকরণ → virtio → IOMMU-সহ passthrough/SR-IOV; overcommit: ballooning, KSM, swapping.
- Pre-copy migration-এ রাউন্ডের অনুপাত r = D/B; r < 1 হলে downtime ছোট, নইলে auto-converge বা post-copy; নিরাপত্তায় ছোট device model, sandbox-এ QEMU, হালনাগাদ আর side channel-এর প্রতিকার।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৫১ · Container-এর ভেতর — namespace, cgroup আর Dockerপরবর্তী পর্বএক kernel ভাগ করে হালকা ঘেরাটোপ।
- অপারেটিং সিস্টেম · কোর্স হোম৬৪টি পর্বপুরো কোর্সের রোডম্যাপ — ১০টি মডিউল।
- পর্ব ৩৩ · TLB আর বড় page table — multilevel, hashed আর invertedপেছনে ফিরেচার স্তরের walk, TLB reach আর huge page — EPT-র হিসাবের ভিত্তি।
- পর্ব ৩৯ · I/O system — polling, interrupt, DMA আর device driverপেছনে ফিরেDMA, descriptor ring আর IOMMU — virtio আর passthrough বোঝার জন্য।
- Computer Fundamentals · Cloud computingসহজ পরিচিতিIaaS, PaaS, SaaS — virtualization-এর ওপর দাঁড়ানো ব্যবসা।