<?php
/**
 * ============================================================
 *  现代操作系统 · 第七章《虚拟化与云》大白话 + 代码例子
 * ============================================================
 *  作用:19 个虚拟化/云概念,每条 = 大白话 + 一段 PHP 代码示例。
 *  说明:虚拟化多为机制与结构,用 PHP 代码模拟其思想。
 *  运行:php virtualization.php            全部
 *        php virtualization.php 277        看第 277(影子页表)
 *        php virtualization.php 虚拟机      关键词搜索
 * ============================================================
 */

declare(strict_types=1);

final class Topic
{
    public function __construct(
        public readonly int $no,
        public readonly string $title,
        public readonly string $plain,
        public readonly string $code
    ) {}
}

final class VirtualizationBook
{
    /** @var Topic[] */
    private array $topics = [];

    public function __construct()
    {
        $this->load();
    }

    private function load(): void
    {
        $data = [
            271 => ['虚拟化的历史与意义',
                '用软件把一台物理机切成多台"虚拟机",每台跑自己的系统,省硬件、好隔离、易管理。',
                <<<'CODE'
$physical = ['cpu' => 16, 'ram' => 64];   // 一台真机
$vms = [                                  // 切成多台虚拟机
    'vm1' => ['cpu' => 4, 'ram' => 16, 'os' => 'Linux'],
    'vm2' => ['cpu' => 4, 'ram' => 16, 'os' => 'Windows'],
];
// 一台硬件跑多套系统, 互相隔离, 省钱省电
CODE],

            272 => ['虚拟化的要求',
                'Popek-Goldberg 准则:所有"敏感指令"(会动硬件状态的)都必须是"特权指令"才能虚拟。',
                <<<'CODE'
function canVirtualize($sensitive, $privileged) {
    // 敏感指令 必须是 特权指令的子集, 才能被VMM拦下
    return empty(array_diff($sensitive, $privileged));
}
echo canVirtualize(['SETCR3'], ['SETCR3','HLT']) ? "可虚拟" : "不可";
CODE],

            273 => ['第一类虚拟机管理程序',
                'Hypervisor 直接装在裸机上(没有底层OS),自己当操作系统管硬件,VM 跑在它上面。',
                <<<'CODE'
// Type-1: 直接跑在硬件上 (如 ESXi/Xen)
$stack = [
    'layer3' => '虚拟机们(各自的OS)',
    'layer2' => 'Type-1 Hypervisor',  // 紧贴硬件, 自己就是OS
    'layer1' => '物理硬件',
];
CODE],

            274 => ['第二类虚拟机管理程序',
                'Hypervisor 作为普通程序装在已有操作系统上(如 VMware Workstation),借宿主 OS 管硬件。',
                <<<'CODE'
// Type-2: 跑在宿主OS之上 (如 VMware Workstation/VirtualBox)
$stack = [
    'layer4' => '虚拟机(客户OS)',
    'layer3' => 'Type-2 Hypervisor',  // 只是宿主上的一个应用
    'layer2' => '宿主操作系统',
    'layer1' => '物理硬件',
];
CODE],

            275 => ['半虚拟化',
                '改造客户 OS,让它知道自己在虚拟机里,主动用"超级调用"求 Hypervisor 办事,更快。',
                <<<'CODE'
// 客户OS被改过: 不偷偷执行敏感指令, 而是主动喊VMM
function hypercall($vmm, $op, $args) {
    return $vmm->handle($op, $args);  // 客户OS显式请求(超级调用)
}
hypercall($vmm, 'update_page_table', [$pte]); // 比"偷偷做被抓"高效
CODE],

            276 => ['内存的虚拟化',
                '客户OS以为自己管物理内存,其实它的"物理地址"还要被 VMM 再翻译一层到真实机器内存。',
                <<<'CODE'
// 两层翻译: 客户虚拟 -> 客户物理 -> 机器物理
function translate($guestVirtual, $guestPT, $vmmMap) {
    $guestPhysical = $guestPT[$guestVirtual];   // 客户OS翻译第一层
    return $vmmMap[$guestPhysical];             // VMM再翻译到真内存
}
CODE],

            277 => ['影子页表',
                'VMM 维护一张"影子页表",直接把客户虚拟地址映射到真实机器地址,省去每次两层翻译。',
                <<<'CODE'
function buildShadowPT($guestPT, $vmmMap) {
    $shadow = [];
    foreach ($guestPT as $gv => $gp)
        $shadow[$gv] = $vmmMap[$gp];  // 合并两层成一张影子表
    return $shadow;                   // CPU直接用它, 一步到位
}
CODE],

            278 => ['I/O 的虚拟化',
                '多台 VM 想用同一套硬盘网卡,VMM 得把它们的 I/O 请求拦下、转译、复用到真实设备。',
                <<<'CODE'
function virtualIO($vm, $request, $realDevice) {
    $translated = remap($vm, $request); // 把VM的设备请求转译
    return $realDevice->execute($translated); // 复用到真实硬件
}
// 多个VM的磁盘请求, 都被VMM调度到同一块物理盘
CODE],

            279 => ['虚拟设备',
                'VMM 给每台 VM 造出"假"的网卡、硬盘等,客户OS装个驱动就当真设备用。',
                <<<'CODE
class VirtualNIC {                     // 给VM的假网卡
    public function send($packet) {
        return forwardToRealNIC($packet); // 背后转给真网卡
    }
}
$vm->attach(new VirtualNIC());         // 客户OS以为是真网卡
CODE],

            280 => ['虚拟机管理程序',
                'Hypervisor 的总职责:分配资源、隔离各 VM、拦截敏感指令、模拟硬件,是虚拟化的核心。',
                <<<'CODE'
class Hypervisor {
    public array $vms = [];
    public function trap($vm, $instruction) {   // 拦截敏感指令
        return $this->emulate($instruction);    // 模拟执行
    }
    public function schedule() { /* 给各VM分CPU时间 */ }
}
CODE],

            281 => ['虚拟机迁移',
                '把正在运行的整台 VM(内存、状态)从一台物理机搬到另一台,几乎不中断服务(热迁移)',
                <<<'CODE'
function liveMigrate($vm, $src, $dst) {
    foreach ($vm->memoryPages as $p)
        $dst->copy($p);               // 1.边运行边拷贝内存页
    $vm->pause();                     // 2.短暂暂停
    $dst->copy($vm->dirtyPages());    // 3.补拷脏页+CPU状态
    $dst->resume($vm);                // 4.在新机器上继续跑
}
CODE],

            282 => ['不可虚拟化的硬件',
                '老 x86 有些敏感指令在用户态不报错也不被拦(没法trap),得靠二进制翻译等手段补救。',
                <<<'CODE'
$problematicInstr = ['POPF']; // 改标志位, 用户态执行被默默忽略, 抓不到
function binaryTranslate($code) {
    // 扫描代码, 把抓不到的敏感指令换成可被VMM处理的调用
    return str_replace('POPF', 'CALL vmm_popf', $code);
}
CODE],

            283 => ['许可证问题',
                '虚拟化让一份软件可能同时跑在多台 VM/多核上,按物理机还是按 VM 收费成了法律难题。',
                <<<'CODE'
function licenseCost($software, $mode, $physicalCpus, $vmCount) {
    return match ($mode) {
        'per_physical' => $software['price'] * $physicalCpus, // 按物理核
        'per_vm'       => $software['price'] * $vmCount,      // 按虚拟机
    };
}
CODE],

            284 => ['云的概念',
                '把计算/存储当水电一样按需取用:要多少开多少、用多少付多少,不用自己买机器。',
                <<<'CODE'
$cloud = [
    'on_demand'   => true,            // 按需开通
    'elastic'     => true,            // 弹性伸缩
    'pay_per_use' => true,            // 用多少付多少
];
function rentVM($hours, $ratePerHour) { return $hours * $ratePerHour; }
CODE],

            285 => ['云即服务',
                '云分三层卖:IaaS(卖虚拟机/存储)、PaaS(卖运行平台)、SaaS(直接卖现成软件)',
                <<<'CODE'
$serviceModels = [
    'IaaS' => '卖基础设施: 虚拟机/存储/网络',  // 如 EC2
    'PaaS' => '卖平台: 直接部署代码',          // 如 App Engine
    'SaaS' => '卖软件: 开箱即用',              // 如 Gmail
];
CODE],

            286 => ['云的迁移',
                '把本地的应用和数据搬上云,或在不同云之间搬;要处理兼容、停机、数据搬运等问题。',
                <<<'CODE'
function migrateToCloud($app, $cloud) {
    $cloud->provision($app['requirements']); // 1.云端备好资源
    $cloud->upload($app['data']);             // 2.搬数据
    $cloud->deploy($app['code']);             // 3.部署应用
    switchTraffic($app, $cloud);              // 4.切流量过去
}
CODE],

            287 => ['检查点',
                '定时把 VM 的完整状态存个快照;出问题能回退到快照,也是迁移和容错的基础。',
                <<<'CODE'
function checkpoint($vm) {
    return [                          // 拍一张完整快照
        'memory' => $vm->dumpMemory(),
        'cpu'    => $vm->cpuState(),
        'disk'   => $vm->diskSnapshot(),
    ];
}
function restore($vm, $snapshot) { $vm->loadState($snapshot); } // 回退
CODE],

            288 => ['虚拟机监控器 VMM',
                'VMM 就是 Hypervisor 的别名:监控并仲裁所有 VM 对硬件的访问,是那个"看门人"',
                <<<'CODE'
class VMM {                            // = Hypervisor
    public function onSensitiveAccess($vm, $resource) {
        if (!$this->allowed($vm, $resource)) deny();
        return $this->mediate($vm, $resource); // 仲裁每次硬件访问
    }
}
CODE],

            289 => ['类型 1 与类型 2 的混合',
                '现代方案常融合两类优点,如 KVM:Linux 内核(宿主)里嵌一个 Type-1 式的硬件加速模块。',
                <<<'CODE'
// KVM 模式: 宿主Linux + 内核态硬件虚拟化模块
$kvm = [
    'host'        => 'Linux',         // 像Type-2有完整宿主OS
    'accelerator' => 'kernel module', // 又像Type-1直接用硬件虚拟化(VT-x)
    'devices'     => 'QEMU 模拟',
];
CODE],
        ];

        foreach ($data as $no => [$title, $plain, $code]) {
            $this->topics[$no] = new Topic($no, $title, $plain, $code);
        }
    }

    public function renderAll(): void
    {
        $this->printHeader('现代操作系统 · 第七章《虚拟化与云》大白话 + 代码例子');
        foreach ($this->topics as $t) $this->printTopic($t);
        $this->printFooter(count($this->topics));
    }

    public function renderOne(int $no): void
    {
        if (!isset($this->topics[$no])) {
            echo "⚠️  没有第 {$no} 条(本章 271~289)\n";
            return;
        }
        $this->printHeader("第 {$no} 条");
        $this->printTopic($this->topics[$no]);
    }

    public function search(string $kw): void
    {
        $hit = array_filter(
            $this->topics,
            fn(Topic $t) => mb_strpos($t->title, $kw) !== false
                         || mb_strpos($t->plain, $kw) !== false
                         || mb_strpos($t->code, $kw) !== false
        );
        if (!$hit) { echo "🔍 没找到包含“{$kw}”的条目\n"; return; }
        $this->printHeader("搜索“{$kw}”,命中 " . count($hit) . " 条");
        foreach ($hit as $t) $this->printTopic($t);
    }

    private function printHeader(string $title): void
    {
        echo "\n" . str_repeat('=', 62) . "\n  {$title}\n" . str_repeat('=', 62) . "\n";
    }

    private function printTopic(Topic $t): void
    {
        printf("\n【%03d】%s\n", $t->no, $t->title);
        echo "  ▷ 大白话:" . wordwrap_cn($t->plain, 36, "\n            ") . "\n";
        echo "  ▶ 代码例子:\n";
        foreach (explode("\n", $t->code) as $line) {
            echo "      | " . $line . "\n";
        }
    }

    private function printFooter(int $count): void
    {
        echo "\n" . str_repeat('-', 62) . "\n";
        echo "  共 {$count} 条,每条含“大白话 + PHP代码例子”。\n";
        echo str_repeat('-', 62) . "\n";
    }
}

/** 中文换行 */
function wordwrap_cn(string $text, int $width, string $break): string
{
    $len = mb_strlen($text);
    if ($len <= $width) return $text;
    $out = '';
    for ($i = 0; $i < $len; $i += $width) {
        $out .= mb_substr($text, $i, $width);
        if ($i + $width < $len) $out .= $break;
    }
    return $out;
}

// ===================== 入口 =====================
$book = new VirtualizationBook();
$arg = $argv[1] ?? null;
if ($arg === null)            $book->renderAll();
elseif (ctype_digit($arg))    $book->renderOne((int) $arg);
else                          $book->search($arg);
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐