现代操作系统=多处理器系统
【代码】现代操作系统=多处理器系统。
·
<?php
/**
* ============================================================
* 现代操作系统 · 第八章《多处理器系统》大白话 + 代码例子
* ============================================================
* 作用:30 个多处理器/多计算机/分布式概念,每条 = 大白话 + PHP 代码示例。
* 说明:多为硬件结构与并行/分布式机制,用 PHP 代码模拟其思想。
* 运行:php multiprocessor.php 全部
* php multiprocessor.php 308 看第 308 条(RPC)
* php multiprocessor.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 MultiprocessorBook
{
/** @var Topic[] */
private array $topics = [];
public function __construct()
{
$this->load();
}
private function load(): void
{
$data = [
290 => ['多处理器系统硬件',
'一台机器里装多个 CPU,它们共享同一份内存,靠总线或交换网络连起来一起干活。',
<<<'CODE'
$system = [
'cpus' => ['cpu0', 'cpu1', 'cpu2', 'cpu3'],
'memory' => 'shared', // 共享同一份内存
'connect'=> 'bus', // 靠总线/交换网络互连
];
CODE],
291 => ['UMA 多处理器',
'统一内存访问:每个 CPU 访问任何内存的速度都一样(对称、好编程,但总线易堵)。',
<<<'CODE'
function umaAccessTime($cpu, $addr) {
return 100; // 不管哪个CPU、哪块内存, 延迟都一样
}
echo umaAccessTime('cpu0', 0x1000); // 100
echo umaAccessTime('cpu3', 0xFFFF); // 100 (相同)
CODE],
292 => ['NUMA 多处理器',
'非统一内存访问:每个 CPU 有"近"内存(快)和"远"内存(慢),扩展性好但要会就近放数据。',
<<<'CODE'
function numaAccessTime($cpu, $memNode) {
return $cpu == $memNode ? 100 : 300; // 本地内存快, 远端慢3倍
}
echo numaAccessTime(0, 0); // 100 本地
echo numaAccessTime(0, 3); // 300 远端
CODE],
293 => ['多处理器操作系统类型',
'管多 CPU 的三种思路:各管各的、一主多从、全对称(SMP)。',
<<<'CODE'
$osTypes = [
'private' => '每个CPU一套独立OS',
'master_slave' => '一个主CPU管全部',
'smp' => '所有CPU平等共享一套OS',
];
CODE],
294 => ['每个 CPU 有自己的操作系统',
'把内存切块,每个 CPU 跑一份独立 OS,互不通气;简单但资源没法共享、负载不均。',
<<<'CODE'
$cpus = [
0 => ['os' => 'copy0', 'mem' => '0-1G'], // 各跑各的OS
1 => ['os' => 'copy1', 'mem' => '1-2G'],
];
// 缺点: cpu0 忙死, cpu1 闲死, 无法互相帮忙
CODE],
295 => ['主从多处理器',
'一个主 CPU 专门跑操作系统和调度,其它从 CPU 只跑用户程序;主 CPU 易成瓶颈。',
<<<'CODE'
function masterSlave($task, &$cpus) {
if ($task['type'] == 'syscall')
$cpus['master']->handle($task); // 系统调用全交给主CPU
else
$cpus['slave'][0]->run($task); // 用户程序丢给从CPU
}
CODE],
296 => ['对称多处理器 SMP',
'所有 CPU 平等,都能跑 OS 也能跑用户程序,用锁保护内核共享数据;现代主流。',
<<<'CODE'
$kernelLock = false;
function smpEnterKernel(&$lock) {
while (!compareAndSwap($lock, false, true)) { /* 自旋等 */ }
// 进入内核临界区, 任意CPU都平等竞争
}
function smpLeaveKernel(&$lock) { $lock = false; }
CODE],
297 => ['多处理器同步',
'多个 CPU 同时改一份数据要同步;单机的关中断没用了,得靠原子指令(TSL/CAS)。',
<<<'CODE'
function atomicTSL(&$lock) { // 硬件原子: 多CPU也安全
$old = $lock; $lock = 1; return $old;
}
// 多CPU场景: 关中断无效, 必须用总线锁定的原子指令
CODE],
298 => ['自旋锁与忙等待',
'锁占用时间极短时,CPU 原地打转反复试(自旋)比睡眠唤醒更划算,省掉切换开销。',
<<<'CODE'
function spinLock(&$lock) {
while (atomicTSL($lock) != 0) {
// 原地自旋, 不睡 (切换比短暂等待还贵)
}
}
function spinUnlock(&$lock) { $lock = 0; }
CODE],
299 => ['多处理器调度',
'不仅要决定"跑哪个进程",还要决定"在哪个 CPU 上跑",且尽量别乱迁移(伤缓存)。',
<<<'CODE'
function schedule($proc, $cpus) {
// 优先放回上次跑的CPU (亲和性, 缓存还热)
return $proc['lastCpu'] ?? leastBusy($cpus);
}
CODE],
300 => ['时间共享调度',
'所有 CPU 共用一个就绪队列,谁空了就来队列里抓一个跑;简单但队列要加锁、伤亲和性。',
<<<'CODE'
$readyQueue = new SplQueue();
function timeSharing(&$queue, $cpu) {
lock($queue);
$proc = $queue->isEmpty() ? null : $queue->dequeue(); // 共享队列抓一个
unlock($queue);
if ($proc) $cpu->run($proc);
}
CODE],
301 => ['空间共享调度',
'把相关的一组线程一次性分给一批 CPU 同时跑,跑完才换,适合要紧密协作的并行程序。',
<<<'CODE'
function spaceSharing($threadGroup, $cpus) {
foreach ($threadGroup as $i => $thread)
$cpus[$i]->assign($thread); // 一组线程占住一批CPU
// 全组一起跑, 不被打散
}
CODE],
302 => ['群调度',
'空间+时间结合:把一组协作线程"成群"地同时调度上 CPU,让它们能互相即时通信。',
<<<'CODE'
function gangSchedule($gang, $cpus, $timeSlice) {
foreach ($gang as $i => $thread)
$cpus[$i]->run($thread, $timeSlice); // 整群同一时间片一起上
// 它们能即时互相通信, 不会一个在跑一个在等
}
CODE],
303 => ['多计算机硬件',
'多台独立计算机(各有自己内存)用高速网络连起来,又叫集群;不共享内存,靠收发消息。',
<<<'CODE'
$cluster = [
'node0' => ['cpu'=>1, 'mem'=>'private'], // 各有私有内存
'node1' => ['cpu'=>1, 'mem'=>'private'],
'link' => 'high-speed network', // 靠网络连
];
CODE],
304 => ['互连技术',
'节点怎么连:网格、超立方体、环、树等拓扑,影响通信距离和带宽。',
<<<'CODE'
$topologies = [
'grid' => '网格, 邻居相连',
'hypercube' => '超立方体, 距离短',
'ring' => '环形',
'tree' => '树形',
];
CODE],
305 => ['网络接口',
'每个节点有块网卡负责收发包,自带缓冲和处理器,减轻主 CPU 的通信负担。',
<<<'CODE'
$nic = [
'sendBuffer' => [], // 发送缓冲
'recvBuffer' => [], // 接收缓冲
'onboardCpu' => true, // 网卡自带处理器, 分担主CPU
];
CODE],
306 => ['低层通信软件',
'直接操作网卡收发包的底层代码,追求零拷贝、少干预,把数据快速送进送出。',
<<<'CODE'
function lowLevelSend($nic, $packet) {
$nic['sendBuffer'][] = $packet; // 直接塞进网卡缓冲
$nic['trigger'](); // 触发硬件发送(尽量零拷贝)
}
CODE],
307 => ['用户层通信软件',
'给程序用的收发接口:send/receive 原语,分阻塞(等到完成)和非阻塞(立即返回)。',
<<<'CODE'
function send($dest, $msg, $blocking = true) {
enqueueToNic($dest, $msg);
if ($blocking) waitUntilSent(); // 阻塞: 等发完才返回
// 非阻塞: 立即返回, 后台慢慢发
}
function receive($src) { return blockUntilArrive($src); }
CODE],
308 => ['远程过程调用 RPC',
'让调远程机器上的函数像调本地函数一样:参数打包发过去,执行后结果传回来。',
<<<'CODE'
function rpcCall($host, $func, $args) {
$request = serialize(['func'=>$func, 'args'=>$args]); // 客户端打包(marshal)
$response = sendToServer($host, $request); // 发到远端执行
return unserialize($response); // 拆包返回结果
}
$sum = rpcCall('node1', 'add', [3, 5]); // 像本地调用一样
CODE],
309 => ['分布式共享存储器 DSM',
'多台无共享内存的机器,靠软件假装出一片"共享内存",按页在网络上搬来搬去。',
<<<'CODE'
function dsmAccess($page, $localPages, $remoteNodes) {
if (isset($localPages[$page])) return $localPages[$page]; // 本地有
$data = fetchPageOverNetwork($page, $remoteNodes); // 没有就网络抓页
$localPages[$page] = $data; // 缓存到本地
return $data;
}
CODE],
310 => ['多计算机调度',
'不光排时间,还要决定每个进程放到哪台机器上跑,尽量减少跨机通信。',
<<<'CODE'
function placeProcess($proc, $nodes) {
// 把通信频繁的进程放同一台机, 减少网络往返
return $proc['talksTo']
? sameNodeAs($proc['talksTo'])
: leastLoaded($nodes);
}
CODE],
311 => ['负载平衡',
'别让有的机器忙死有的闲死;把任务从重载节点挪到轻载节点,分发送/接收两种发起方式。',
<<<'CODE'
function loadBalance(&$nodes) {
$busy = maxLoad($nodes); $idle = minLoad($nodes);
if ($nodes[$busy]['load'] - $nodes[$idle]['load'] > 2) {
$task = array_pop($nodes[$busy]['tasks']);
$nodes[$idle]['tasks'][] = $task; // 重载挪给轻载
}
}
CODE],
312 => ['分布式系统',
'一堆联网的独立计算机,对用户却像一台机器;比多计算机更松散、跨地域、异构。',
<<<'CODE'
$distributed = [
'nodes' => ['北京', '上海', '广州'], // 跨地域
'transparent' => true, // 用户感觉像用一台机
'coupling' => 'loose', // 松耦合, 各自独立
];
CODE],
313 => ['网络硬件',
'连接分布式节点的物理网络:以太网(局域)、广域网、交换机路由器等。',
<<<'CODE'
$networkHardware = [
'LAN' => '以太网, 局域, 高速',
'WAN' => '广域网, 跨城市/国家',
'switch' => '交换机, 局域内转发',
'router' => '路由器, 网络间选路',
];
CODE],
314 => ['网络服务与协议',
'通信要守共同规矩(协议):分层(如 TCP/IP),各层管各的事,下层给上层提供服务。',
<<<'CODE'
$stack = [
'application' => 'HTTP/FTP', // 应用层
'transport' => 'TCP/UDP', // 传输层(可靠/不可靠)
'network' => 'IP', // 网络层(寻址路由)
'link' => 'Ethernet', // 链路层
];
CODE],
315 => ['中间件',
'架在操作系统和应用之间的一层软件,抹平各机器差异,提供统一的分布式编程模型。',
<<<'CODE'
// 中间件: 让上层应用不用管底下是什么OS/网络
class Middleware {
public function call($service, $args) {
return $this->locate($service)->invoke($args); // 屏蔽分布细节
}
}
CODE],
316 => ['基于文档的中间件',
'把信息组织成互相超链接的文档,靠 URL 定位、点链接跳转,万维网就是典型。',
<<<'CODE'
// Web 模型: 文档 + 超链接 + URL
$page = [
'url' => 'http://site/a.html',
'links' => ['http://site/b.html', 'http://other/c.html'], // 超链接跳转
];
CODE],
317 => ['基于文件系统的中间件',
'把整个分布式系统做成一个大文件系统,远程文件像本地文件一样读写(如 NFS)。',
<<<'CODE'
// 远程文件当本地用 (类似 NFS 挂载)
mount('node1:/data', '/mnt/remote'); // 挂载远程目录
$content = file_get_contents('/mnt/remote/a.txt'); // 像读本地文件
CODE],
318 => ['基于对象的中间件',
'把远程资源封装成对象,调用远程对象的方法像调用本地对象(如 CORBA、Java RMI)。',
<<<'CODE'
// 远程对象: 拿到代理, 调方法像本地一样
$remoteObj = $orb->resolve('BankAccount@node2');
$remoteObj->deposit(100); // 实际在远端机器上执行
CODE],
319 => ['基于协作的中间件',
'面向"协调与共享"的模型,如发布/订阅、共享元组空间(Linda),让进程松耦合地交流。',
<<<'CODE'
// 元组空间 (Linda 模型): 谁都能丢/取数据, 不需直接认识对方
$tupleSpace = [];
function out(&$ts, $tuple) { $ts[] = $tuple; } // 发布
function in(&$ts, $pattern) { // 按模式取走
foreach ($ts as $k => $t)
if (match_pattern($t, $pattern)) { unset($ts[$k]); return $t; }
}
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} 条(本章 290~319)\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 MultiprocessorBook();
$arg = $argv[1] ?? null;
if ($arg === null) $book->renderAll();
elseif (ctype_digit($arg)) $book->renderOne((int) $arg);
else $book->search($arg);
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐



所有评论(0)