操作系统进程调度算法实现:从FCFS到时间片轮转的代码级解析
1. 项目概述从“调度”二字看透进程管理的核心“进程的调度”这五个字听起来有点学术但如果你把它想象成一家繁忙餐厅的后厨瞬间就明白了。厨师CPU只有一位但点菜单进程却源源不断地递进来有要求快炒的凉菜交互式进程有需要慢炖的汤计算密集型进程还有随时可能加急的VIP订单高优先级进程。这位唯一的厨师如何决定先做哪道菜、做多久、以及什么时候换下一道菜才能让所有食客用户都尽可能满意不至于有人饿晕也不会让VIP暴跳如雷这个决策过程就是操作系统的进程调度。课堂练习3.3正是带我们亲手设计并实现这个“后厨调度算法”。它绝不是让你死记硬背几个算法名字而是要求你深入代码层面理解调度器是如何维护就绪队列、如何依据特定策略挑选下一个运行的进程、以及如何进行进程上下文切换的。通过这个练习你将不再对“先来先服务”、“短作业优先”、“时间片轮转”这些名词感到抽象你会看到它们是如何通过几行关键的判断逻辑和队列操作来实现的并深刻体会到不同调度策略对系统平均周转时间、响应时间等核心指标产生的截然不同的影响。无论你是计算机专业的学生还是希望夯实底层知识的开发者这次动手实践都能让你对操作系统的“大脑”如何高效分配其最宝贵的资源——CPU时间有一个通透而扎实的理解。2. 核心需求与设计思路拆解2.1 练习的核心目标与场景还原这个练习通常模拟一个简化的操作系统内核环境其中包含一个调度器模块和多个模拟的进程控制块PCB。你的核心任务就是实现这个调度器模块中的核心调度函数。给定的输入可能是一系列进程的到达时间、预计运行时间服务时间和优先级等信息。调度器需要根据指定的算法策略模拟CPU时间的推进决定在每个时间点应该运行哪个进程并最终输出每个进程的完成时间、周转时间等结果。其深层需求在于理解就绪队列的管理所有到达但未运行的进程都放在就绪队列中。调度算法本质上是对这个队列进行排序和选择的一系列规则。你需要熟练掌握队列或优先队列这种数据结构在此处的应用。掌握调度决策的触发时机调度并非每时每刻都在发生。通常当正在运行的进程主动放弃CPU如执行完毕、等待I/O或被强制剥夺CPU如时间片用完时才会触发调度器重新选择。量化评估算法优劣通过计算平均周转时间从进程提交到完成的时间、平均带权周转时间周转时间与服务时间的比值等指标直观对比“先来先服务FCFS”和“短作业优先SJF”等算法在公平性和效率上的权衡。2.2 关键数据结构设计模拟进程控制块PCB在动手写调度逻辑之前设计好承载进程信息的数据结构至关重要。一个简化的PCB需要包含以下核心字段typedef struct pcb { int pid; // 进程ID唯一标识 int arrival_time; // 到达时间进程进入就绪队列的时刻 int burst_time; // 服务时间/运行时间进程总共需要占用CPU的时长 int remaining_time;// 剩余运行时间用于时间片轮转等可剥夺调度 int priority; // 优先级数字越小可能优先级越高取决于定义 int finish_time; // 完成时间由调度器计算得出 int turnaround_time; // 周转时间 完成时间 - 到达时间 float weighted_turnaround_time; // 带权周转时间 周转时间 / 服务时间 struct pcb *next; // 指针用于链接成队列 } PCB;注意在简单模拟中我们通常假设所有进程一旦开始运行就会持续占用CPU直到完成或时间片用完忽略I/O等待等复杂状态。remaining_time初始等于burst_time随着调度执行而递减。2.3 调度算法选型背后的逻辑练习可能会要求实现多种算法每一种都有其鲜明的特点和适用场景先来先服务FCFS核心思想就像普通的排队谁先到就绪队列谁就先获得CPU。实现关键维护一个简单的先进先出FIFO队列。新到达的进程直接插入队尾调度时总是从队头取出进程运行。为什么学它它是理解调度概念的基础实现最简单。但其缺点也明显对短作业不友好“护航效应”平均等待时间可能较长。短作业优先SJF核心思想从就绪队列中挑选预计运行时间最短的进程优先运行。实现关键不能再用简单队列。需要在每次调度时遍历就绪队列找出burst_time或remaining_time最小的进程。这通常意味着需要将就绪队列按运行时间排序或者使用优先队列最小堆数据结构。为什么学它理论上它可以给出最小的平均等待时间。但问题是长作业可能被“饿死”始终得不到调度。这引出了对“抢占式”调度的思考。时间片轮转RR核心思想给每个进程分配一个固定的CPU时间片如10ms。进程运行一个时间片后如果还未完成则被剥夺CPU并放回就绪队列队尾等待下一轮调度。实现关键维护一个FIFO队列。新进程到达插入队尾。调度时队头进程运行一个时间片然后检查其remaining_time。若大于0则将其移至队尾若等于0则进程完成移出队列。然后调度新的队头进程。为什么学它这是分时系统的基石能保证所有进程获得一定的响应能力公平性好。时间片大小的设置是一个关键权衡太大退化为FCFS太小则上下文切换开销过大。3. 核心细节解析与实操要点3.1 模拟时钟推进与事件驱动操作系统调度是随着时间推移动态发生的。在我们的模拟程序中需要一个核心的“模拟时钟”来驱动整个流程。通常有两种模拟思路时间步进法以一个最小时间单位如1个时间单位逐步增加当前时间current_time。在每个时间点检查是否有新进程到达arrival_time current_time将其加入就绪队列然后检查当前运行的进程是否结束或时间片用完决定是否触发调度。int current_time 0; PCB *running_process NULL; int time_slice_used 0; // 记录当前进程已使用的时间片 while (有进程未完成) { // 1. 处理到达事件 while (有进程在current_time到达) { 将该进程加入就绪队列(根据算法排序); } // 2. 处理调度事件 if (running_process NULL || 当前进程应被剥夺CPU) { schedule(); // 调用调度函数选择下一个进程 time_slice_used 0; // 重置时间片计数器 } // 3. 执行一个单位时间 if (running_process ! NULL) { running_process-remaining_time--; time_slice_used; // 检查进程是否完成 if (running_process-remaining_time 0) { running_process-finish_time current_time 1; // 注意完成时间点是下一时刻开始前 running_process NULL; } // 检查时间片是否用完 (针对RR算法) if (time_slice_used TIME_SLICE) { // 将running_process放回就绪队列队尾 running_process NULL; } } current_time; }实操心得时间步进法逻辑清晰易于理解和调试特别适合初学者。但效率不高如果总模拟时间很长循环次数会很多。事件驱动法不逐步推进时间而是维护一个未来事件列表如下一个进程到达时间、当前进程预计结束时间。每次都跳到下一个最近的事件点去处理处理完后更新事件列表。这种方法效率高更贴近真实调度器的实现思想但逻辑更复杂。对于课堂练习强烈建议使用时间步进法它能让调度过程的每一步都清晰可见便于你插入打印语句来调试和观察队列变化。3.2 就绪队列的实现与算法耦合不同的调度算法要求就绪队列有不同的组织方式FCFS/RR算法一个简单的FIFO队列足矣。可以用链表实现enqueue操作在尾插入dequeue操作从头部取出。SJF非抢占式算法队列需要按进程的burst_time升序排列。每次有新进程加入或当前进程完成时都需要扫描队列找到合适的位置插入或者直接使用一个最小堆来维护这样每次取出的队首元素就是最短作业。优先级调度与SJF类似但排序依据是priority字段。一个常见的坑是在模拟开始时就绪队列可能是空的。第一个到达的进程到来之前CPU是空闲的。你的调度函数和时钟推进循环必须能正确处理这种情况。3.3 上下文切换的模拟在真实操作系统中调度伴随着昂贵的上下文切换保存和恢复寄存器状态。在我们的模拟里虽然不涉及真实的寄存器操作但必须体现其逻辑和开销。逻辑体现调度函数schedule()被调用时它的核心动作就是改变running_process这个指针的指向。从指向旧进程变为指向新选出的进程这就是一次上下文切换的抽象。开销体现更高级的模拟可能会要求你考虑上下文切换的时间开销。例如假设一次切换需要switch_cost个单位时间。那么在每次schedule()被调用、且running_process发生改变时current_time需要额外增加switch_cost。这段时间内CPU没有执行任何用户进程代码。这个细节能让你更深刻地理解过于频繁的调度如RR算法时间片过小会导致系统吞吐量下降。4. 实操过程与核心环节实现下面我们以实现非抢占式SJF调度和时间片轮转RR调度为例展示核心代码逻辑。4.1 非抢占式短作业优先SJF实现详解假设我们使用一个链表来实现按服务时间排序的就绪队列。// 将进程按burst_time升序插入就绪队列 void enqueue_sjf(PCB **ready_queue, PCB *new_process) { PCB *current *ready_queue; PCB *prev NULL; // 寻找插入位置找到第一个burst_time大于新进程的节点 while (current ! NULL current-burst_time new_process-burst_time) { prev current; current current-next; } // 插入节点 new_process-next current; if (prev NULL) { *ready_queue new_process; // 插入队头 } else { prev-next new_process; } } // 调度函数非抢占式SJF总是运行就绪队列队首的进程 void schedule_sjf(PCB **ready_queue, PCB **running_process, int current_time) { if (*running_process ! NULL) { // 非抢占式只有当前进程主动放弃CPU完成时才会调度 return; } if (*ready_queue ! NULL) { *running_process *ready_queue; // 队首进程出队并运行 *ready_queue (*ready_queue)-next; (*running_process)-next NULL; printf(时间 %d: 调度进程P%d运行服务时间%d\n, current_time, (*running_process)-pid, (*running_process)-burst_time); } }在主循环中当一个进程完成时我们计算其周转时间并将running_process置为NULL这会在下一次循环中触发schedule_sjf去选择下一个最短作业。踩坑记录在非抢占式SJF中“短作业”指的是进程的总服务时间burst_time而不是剩余时间。因为是非抢占的一旦开始运行就会直到完成。所以排序和选择依据始终是burst_time。如果你错误地使用了remaining_time在逻辑上虽然当前没问题因为非抢占下remaining_time等于burst_time但会为后续理解抢占式SJF埋下隐患。4.2 时间片轮转RR实现详解RR算法需要维护一个标准的FIFO队列并引入时间片概念。#define TIME_QUANTUM 4 // 假设时间片大小为4个单位 // RR的就绪队列是简单的FIFO入队到尾 void enqueue_rr(PCB **ready_queue, PCB **queue_tail, PCB *new_process) { new_process-next NULL; if (*queue_tail NULL) { *ready_queue *queue_tail new_process; } else { (*queue_tail)-next new_process; *queue_tail new_process; } } // RR的出队从队头 PCB* dequeue_rr(PCB **ready_queue, PCB **queue_tail) { if (*ready_queue NULL) return NULL; PCB *temp *ready_queue; *ready_queue (*ready_queue)-next; if (*ready_queue NULL) { *queue_tail NULL; } temp-next NULL; return temp; } // RR调度函数 void schedule_rr(PCB **ready_queue, PCB **queue_tail, PCB **running_process, int *time_slice_counter, int current_time) { // 如果当前有进程在运行且时间片没用完则继续运行 if (*running_process ! NULL *time_slice_counter TIME_QUANTUM) { return; } // 当前进程需要被剥夺CPU完成或时间片到 if (*running_process ! NULL) { if ((*running_process)-remaining_time 0) { // 时间片用完但未完成放回就绪队列队尾 printf(时间 %d: 进程P%d时间片用完剩余%d放回队尾\n, current_time, (*running_process)-pid, (*running_process)-remaining_time); enqueue_rr(ready_queue, queue_tail, *running_process); } else { // 进程完成 (*running_process)-finish_time current_time; printf(时间 %d: 进程P%d完成\n, current_time, (*running_process)-pid); } *running_process NULL; } // 从就绪队列队头取出下一个进程运行 *running_process dequeue_rr(ready_queue, queue_tail); if (*running_process ! NULL) { *time_slice_counter 0; // 重置时间片计数器 printf(时间 %d: 调度进程P%d运行剩余时间%d\n, current_time, (*running_process)-pid, (*running_process)-remaining_time); } }在主循环中每个时间单位除了递减running_process-remaining_time还要递增time_slice_counter。当time_slice_counter达到TIME_QUANTUM时就会在下一轮循环中触发schedule_rr进行调度。5. 常见问题与排查技巧实录在实现调度算法模拟时以下几个问题是高频“雷区”5.1 进程完成时间点计算错误这是最容易出错的地方之一。假设我们在时间点t开始运行一个剩余时间为1的进程。错误逻辑t时刻remaining_time从1减为0然后立即将finish_time设为t。正确逻辑进程在t时刻开始执行这最后一个单位时间其执行效果覆盖了整个t到t1的时间区间。因此它实际上是在t1时刻开始时才完成的。所以finish_time应设为t1。排查技巧画一个时间轴。用方格代表一个单位时间标上时间点。仔细推演进程从开始到结束究竟占据了哪几个格子。通常finish_time start_time actual_burst_time。而在步进模拟中actual_burst_time就是进程从开始运行到remaining_time减为0所经历的时间步数。5.2 就绪队列状态更新不及时问题表现为进程已经到达但没有被加入就绪队列或者进程被剥夺后没有正确放回队列。对于到达事件必须在主循环每次时间步进后立即检查是否有进程的arrival_time current_time。确保检查代码在调度逻辑之前否则新到达的进程可能错过本时间点的调度机会。对于时间片用完在RR算法中判断时间片用完的代码if (time_slice_used TIME_SLICE)和实际将进程重新入队的操作必须放在时间片正好耗尽的那个时刻。通常是在主循环中执行完一个单位时间后进行检查和操作。调试建议在每一个关键步骤时间步进、检查到达、执行进程、检查完成、触发调度后都打印出当前的current_time、running_process的PID和剩余时间、以及就绪队列的所有进程PID和剩余时间。通过对比这些快照你能清晰地看到进程状态流转是否正确。5.3 平均周转时间计算偏差计算单个进程的周转时间turnaround_time finish_time - arrival_time看似简单但计算平均值时要注意确保所有进程都已计算必须在模拟循环完全结束后所有进程的finish_time都已赋值再遍历进程列表进行计算。使用浮点数进行除法平均周转时间和平均带权周转时间通常是浮点数。在C语言中确保至少分子或分母是float或double类型否则整数除法会截断小数。float avg_turnaround (float)total_turnaround / process_count;带权周转时间的意义weighted_turnaround turnaround_time / burst_time。这个指标对于短作业更敏感。一个运行时间1秒却等了10秒的进程带权周转时间10比一个运行100秒等了110秒的进程带权周转时间1.1感觉上更“糟糕”。SJF算法正是优化了这个指标的平均值。5.4 算法对比与性能分析表实现完不同算法后用同一组进程数据测试并填写下表能直观看出差异进程到达时间服务时间FCFSSJF非抢占RRq4P108完成时间8周转8完成时间8周转8完成时间20周转20P214完成时间12周转11完成时间5周转4完成时间7周转6P329完成时间21周转19完成时间21周转19完成时间26周转24P435完成时间26周转23完成时间13周转10完成时间15周转12平均周转时间15.2510.2515.5平均带权周转2.561.433.12分析FCFS顺序执行简单公平但短作业P2、P4等待时间很长导致平均指标不佳。SJF让短作业P2、P4插队先执行显著降低了平均周转时间和带权周转时间是最优的。但前提是必须能准确预知作业运行时间且长作业P3被延迟了。RR每个进程都能分到时间片响应快。但进程切换频繁总体完成时间被拉长平均周转时间甚至比FCFS还差但这是为了公平性和响应性付出的代价。通过这样的动手编码、调试和对比分析“进程的调度”就不再是书本上枯燥的定义而是你亲手构建并观察其运行的、有血有肉的机制。你会真正理解为什么现代操作系统的调度器如Linux的CFS会设计得如此复杂——它们是在多种互相冲突的目标吞吐量、响应性、公平性、优先级之间寻找最佳平衡点的艺术。

相关新闻

瑞合信LED字幕WiFi卡安装配置与软件应用全攻略

瑞合信LED字幕WiFi卡安装配置与软件应用全攻略

1. 项目概述:瑞合信LED字幕WiFi卡是什么? 如果你手头有一块传统的单色或双色LED显示屏,想让它摆脱笨重的U盘和电脑直连,实现手机远程更新内容,那瑞合信推出的这款LED字幕WiFi卡,可能就是你在找的“神器”。…

2026/8/7 4:01:18 阅读更多 →
OpenClaw技能包生态全解析:10大神器从安装到开发实战指南

OpenClaw技能包生态全解析:10大神器从安装到开发实战指南

1. 项目概述:OpenClaw与技能包生态最近在AI Agent的圈子里,OpenClaw的热度持续攀升,很多刚接触的朋友都在问同一个问题:这工具装是装上了,但怎么才能让它真正“干活”,变得好用起来?这感觉就像你…

2026/8/7 4:01:18 阅读更多 →
聊聊我对后端技术栈的理解:语言、框架与基础设施

聊聊我对后端技术栈的理解:语言、框架与基础设施

一个后端工程师的成长轨迹,往往始于对API接口的懵懂调试,终于对整套技术生态的权衡与敬畏。我们用着最流行的语言,踩着最稳的框架,却常常忘了问自己:究竟是技术在服务于业务,还是我们在为技术打工&#xff…

2026/8/7 4:01:18 阅读更多 →

最新新闻

pdf怎么转emf?这7款图片与PDF互转工具实测盘点

pdf怎么转emf?这7款图片与PDF互转工具实测盘点

上周四下午,财务在企业微信里催我补交上半年的一沓发票电子版,要求合并成一份PDF、每页尺寸统一。我翻出手机相册里横七竖八拍的那十几张发票照片,有的竖拍、有的横拍,还有两张是在咖啡店暖光灯下拍的,纸面泛黄。直接丢…

2026/8/7 4:44:43 阅读更多 →
MySQL锁机制深度解析:从记录锁、间隙锁到临键锁的实战避坑指南

MySQL锁机制深度解析:从记录锁、间隙锁到临键锁的实战避坑指南

1. 从一次诡异的“超卖”事故说起:为什么我们需要理解锁那天下午,运维的告警电话直接打到了我手机上,说库存系统出现了“超卖”——明明数据库里显示某个热门商品的库存只剩10件,但后台却成功生成了15个待发货订单。整个团队瞬间进…

2026/8/7 4:44:43 阅读更多 →
PDF怎么转BMP?7款图片与PDF互转工具实测盘点,覆盖免费在线与电脑自带方法

PDF怎么转BMP?7款图片与PDF互转工具实测盘点,覆盖免费在线与电脑自带方法

上个月整理报销材料,财务要求把一沓纸质发票扫描成PDF归档,同时还得把其中几页关键票据单独存成BMP图片贴进报销系统。听起来简单,真上手才发现绕了一圈——扫描仪默认出的PDF,系统却非要BMP,手头连个趁手的转换工具都…

2026/8/7 4:44:43 阅读更多 →
pdf怎么拆分?这7款PDF合并与拆分工具盘点帮你理清怎么选

pdf怎么拆分?这7款PDF合并与拆分工具盘点帮你理清怎么选

去年八月我就在报销这件事上狠狠卡过一次壳。财务系统只让传一份总文件,可我手头是六张单独的扫描件,PDF阅读器压根没有合并功能。当时临时在青蓝PDF转换里拖进去、调好顺序,一键合成一份再导出,前后没超过半分钟。这之后我就养成…

2026/8/7 4:44:43 阅读更多 →
Hot-75 颜色分类

Hot-75 颜色分类

解法1:双指针,利用 left、right控制边界class Solution:def sortColors(self, nums: List[int]) -> None:"""Do not return anything, modify nums in-place instead."""# 荷兰旗问题,双指针移动法&#xf…

2026/8/7 4:44:43 阅读更多 →
Ubuntu 22.04与Windows 11双系统安装实战指南:从分区到驱动配置

Ubuntu 22.04与Windows 11双系统安装实战指南:从分区到驱动配置

1. 从“想试试”到“真能用”:为什么你需要一份实机双系统安装指南最近身边好几个朋友都来问我,说想在自己的主力电脑上装个Ubuntu,和Windows组成双系统,但网上的教程要么太老,要么太简略,要么就是一堆虚拟…

2026/8/7 4:43:42 阅读更多 →

日新闻

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南

为什么scrcpy成为Android投屏的终极解决方案:完整实战指南 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 想要将Android手机屏幕完美投射到电脑上,享受大屏操作的自…

2026/8/7 0:00:19 阅读更多 →
如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南

如何在5分钟内掌握Tom Select:打造现代化表单选择器的终极指南 【免费下载链接】tom-select Tom Select is a lightweight (~16kb gzipped) hybrid of a textbox and select box. Forked from selectize.js to provide a framework agnostic autocomplete widget wi…

2026/8/7 0:00:19 阅读更多 →
5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件

5分钟快速上手:NSZ压缩工具终极指南,轻松管理Switch游戏文件 【免费下载链接】nsz NSZ - Homebrew compatible NSP/XCI compressor/decompressor 项目地址: https://gitcode.com/gh_mirrors/ns/nsz 你是否在为Nintendo Switch游戏文件占用大量存储…

2026/8/7 0:00:19 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/6 22:02:27 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/6 22:02:27 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/6 22:02:27 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/5 23:28:39 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/6 22:02:28 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/5 23:46:51 阅读更多 →