news 2026/11/2 11:22:56

银河麒麟V10内存不释放排查与定时回收避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
银河麒麟V10内存不释放排查与定时回收避坑

简介:这份面向运维人员的银河麒麟V10内存管理辅助包,聚焦服务器长期运行后可用内存逐渐减少、内存释放不及时等实际问题,适合需要排查内存泄漏、优化系统稳定性的技术人员参考。压缩包共3个文件,以2个sh脚本和1个txt配置说明为主,体积约2KB,轻量便于部署与快速查阅,脚本与说明搭配可用于日常内存监控和定时处理思路的落地。已有787人学习下载,说明该问题在国产服务器系统运维中具有一定共性。内容围绕内存使用监控、泄漏线索分析与系统参数调整等场景展开,读者可从中获得可复用的排查路径、脚本化处理参考及配置说明,帮助缩短定位时间,并为后续结合top、free、日志审查和补丁更新等手段建立更完整的维护流程提供借鉴。

1. 内存不释放的告警响了三个月:先别急着写定时 drop_caches

银河麒麟V10 上,内存不释放是最容易被误判的一类告警:监控面板的 used 常年在 85% 以上,运维群里每天都有人问要不要重启,真登录上去看free -h,available 还剩一大半。另一种现场完全相反——available 每钟头掉一点,重启就好,第二天接着掉。前者是内核缓存没被回收,后者多半是真泄漏。定时任务能治的是前者,治不了后者;分不清这两者就往上加一条 crontab,等于给服务器定时喂药却不看病。下面按我实际排查的顺序,把这只黑匣子拆开。

2. 先分清是哪一种内存不释放:三种现场与各自的判定命令

内存不释放不是一个故障,是至少三类现象的统称:页缓存和 dentry 缓存没被回收、进程匿名页只涨不跌、内核 Slab 或者内存碎片卡死。三者的处理手段完全不同,前者靠定时回收脚本或者内存压力解决,中者除了重启或限制容器没有任何捷径,后者往往要动内核参数甚至换内核模块。所以第一步不是写脚本,是花十分钟确认自己站在哪一类现场上。

2.1 用 free 和 /proc/meminfo 把账算清楚

free -h的 used 一列是历史遗留字段,它在计算时把 buff/cache 也算了进去,看它判断是否泄漏基本等于瞎猜。真正该盯的是 MemAvailable,它是内核估算的“新进程申请内存时,不用触发 swap 也能拿到的量”,包含了大部分可回收的缓存。MemFree 低得可怜却一切正常,这在 Linux 上是常态,不是故障。

# 一次性把关键字段抓出来,避免在 free 的 used 上纠结 grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached|Shmem|AnonPages|Mapped|Slab|SReclaimable|SUnreclaim|Dirty|Writeback):' /proc/meminfo # 换算成百分比,直接丢进监控或者脚本阈值判断 awk '/^MemTotal:/{t=$2} /^MemAvailable:/{a=$2} END{printf "available=%.1f%%\n", a*100/t}' /proc/meminfo

第二条命令里t和a分别接 MemTotal 与 MemAvailable(单位 kB),END 块做一次除法换算。之所以用 MemAvailable 而不是 MemFree,是因为后者在内核还有大量可回收缓存时也会很低,按它设阈值会导致脚本疯狂触发回收。

还有一个坑:Cached 里混着 Shmem,也就是 tmpfs 和共享内存占用的部分,这部分内存虽然有“缓存”的名字,却不可回收。看到 Cached 很大先别高兴,抓一下 Shmem,如果 Shmem 占了 Cached 的大头,drop_caches写多少次都不会掉一个字节。

# Shmem 占 Cached 的比例,超过五成说明缓存大头是 tmpfs,回收脚本对它无效 awk '/^Cached:/{c=$2} /^Shmem:/{s=$2} END{printf "shmem/cached=%.1f%%\n", s*100/c}' /proc/meminfo # 看谁在吃 tmpfs df -h -t tmpfs

df -h -t tmpfs会列出 /dev/shm、/run 这类挂载点,某些中间件把共享内存或者临时文件写到 /dev/shm 且不清理,表现就是“内存不释放”,实际是文件没删。这种情况该做的是清理文件或者调小 tmpfs 上限,定时 drop_caches 完全无效。

2.2 匿名页只涨不跌:进程 RSS 与 OOM 记录的对照

如果 MemAvailable 单调下降、AnonPages 同步上涨,那基本可以确定是进程真占了内存。这时候要做的是找进程,不是找内核参数。

# 按 RSS 排序看头部进程,RSS 会把共享库重复计算,只用于快速定位嫌疑对象 ps -eo pid,ppid,rss,vsz,comm --sort=-rss | head -15 # 对单个进程取 PSS,按比例分摊共享页,比 RSS 更接近真实占用 pmap -x <PID> | tail -1

ps的 rss 单位是 kB,--sort=-rss表示按 RSS 降序。pmap -x输出的最后一行 Total 里,PSS 那一列才是这个进程真正“独占”的内存份额。系统里装了 smem 的话,smem -t -k -c pss,rss,command | head -20会更直观,但生产环境不一定允许临时装包,pmap是随系统就有的。

真正要判断的是“涨不涨”,单次快照没有意义。我一般会挂一个十分钟一次的采样,跑一小时看趋势。

# 每小时采样一次,连续采六次,观察头部进程 RSS 是否单调上升 for i in $(seq 1 6); do date '+%F %T' ps -eo pid,rss,comm --sort=-rss | head -5 sleep 3600 done

如果某个进程每次采样都比上一次高几十兆,且业务量没有同比上涨,那就是泄漏,这时候定时重启该进程是唯一能在不改进程代码的前提下止血的手段。如果所有进程的 RSS 都稳定,只有 AnonPages 在涨,那要么是泄漏发生在没被列出来的短命进程里,要么是内核模块在申请内存。

再翻一遍历史 OOM 记录,确认这台机器是不是曾经杀过进程——很多时候内存不释放只是表象,真正的问题是某个进程被 OOM killer 干掉后内存又被别的进程吃掉。

# -T 把内核时间戳转成可读时间,老内核不支持就退回 dmesg | grep dmesg -T | grep -iE 'out of memory|oom-killer|killed process' grep -iE 'oom|killed process' /var/log/messages

顺带提一句 glibc 的多线程程序:arena 数量默认跟 CPU 核数挂钩,每个线程一个 arena,空闲后内存不一定归还给系统,表现就是 Java、C++ 服务在压测后 RSS 不回落。常见做法是在启动脚本里加export MALLOC_ARENA_MAX=2,能明显压低峰值后的驻留量。这个不做也行,属于优化项,别当成泄漏去查。

2.3 Slab、dentry 与碎片:内核态那部分内存去哪了

MemAvailable 掉、AnonPages 没怎么涨、进程 RSS 也稳定,那就要怀疑内核对象了。Slab 是内核给 dentry、inode、网络连接等对象分配的内存池,正常情况下 SReclaimable 可以回收,但 SUnreclaim 只增不减时就是问题。

# 按占用排序看内核对象,先看哪一类涨得最快 slabtop -o -s c | head -20 # 没装 procps 的备用方案 awk 'NR>2{print $1, $3, $4}' /proc/slabinfo | sort -k2 -nr | head -15

slabtop -o表示一次输出后退出,-s c按缓存大小排序。盯住 dentry、inode_cache、kmalloc-* 这几类。如果 dentry 单体量特别大,通常是有进程在疯狂遍历目录或访问大量小文件,比如日志采集 agent 扫全盘。这类问题定时写echo 2 > /proc/sys/vm/drop_caches能临时压下去,但根因还是要落回到那个遍历目录的进程上。

再顺手看一眼碎片情况,内存明明够、却申请不到连续大页,这在数据库和虚拟化场景里特别常见。

# buddyinfo 里 order 越大表示连续块越大,高位全是 0 说明碎片严重 cat /proc/buddyinfo # 透明大页当前策略,数据库场景一般建议 madvise cat /sys/kernel/mm/transparent_hugepage/enabled

/proc/buddyinfo每一行的十一个数字对应 order 0 到 order 10 的空闲块数量,最后几个数字长期为 0 说明大块内存已经打碎。碎片问题靠定时 drop_caches 只能缓解一部分,因为回收页缓存本身就是一个把小块重新拼起来的过程。至于透明大页,always在长时间运行后容易引发内存膨胀,madvise是更稳的折中。

3. 定时释放内存的三种做法:drop_caches、重启进程、cgroup 限额各自的边界

确认完现场之后再谈“定时”,否则定时任务只是在掩盖问题。三种手段的侵入性和代价完全不同:drop_caches 侵入最小但收益有限,重启进程能一刀切但会丢状态,cgroup 限额最根本但要求你能控制服务启动方式。多数生产机最后是三者组合。

3.1 drop_caches 的 1/2/3 到底差在哪

这个接口的参数值很多人背下来了却不知道含义,直接写 3 是最常见的误用。

值实际回收的对象代价
1只回收页缓存(page cache)命中率下降,后续读盘变多
2回收 dentry 和 inode 缓存(可回收 Slab)目录遍历、文件查找变慢
3等价于 1 + 2两样代价一起吃
# 必须先 sync,把脏页刷盘,否则 drop 的时候会阻塞在 IO 上 sync # 只回收页缓存,对大多数“缓存高但没泄漏”的机器够用了 echo 1 > /proc/sys/vm/drop_caches

sync这一步经常被省掉,后果是内核在回收时要去处理一大批 Dirty 页,脚本执行时间从毫秒变成几秒,赶上业务高峰就是一次抖动。echo 1 >里的 1 不是字节数,是操作码,写 1、2、3 之外的值内核直接忽略。另外这个值不能通过 sysctl.conf 持久化生效——vm.drop_caches每次写都会被内核处理完重置,重启更是必然丢失,所以必须靠定时任务周期性触发。

提示:数据库服务器上慎用 3。MySQL、PostgreSQL 的缓冲池被清空后,需要重新预热才能回到原来的 QPS,把内存“降下来”的收益远小于性能回落的损失。

3.2 进程重启与 glibc arena:把泄漏按周期截断

对真泄漏的进程,定时重启是唯一能立刻见效的止血方案。它有明显的代价——重启期间服务不可用、连接丢失、缓存重建——所以要么配合优雅停机,要么放在业务低谷。用 systemd 托管的话,给一个定时单元比重启整机干净得多。

# 优雅重启单个服务,不要用 kill -9 硬来 systemctl restart your-service.service # 确认重启后 RSS 确实回落了 systemctl show your-service.service -p MainPID --value | xargs -I{} ps -o pid,rss,etime,comm -p {}

第二条命令先取服务的 MainPID,再交给 ps 打印 RSS 和运行时长。如果重启后 RSS 立刻回到基线、随后又开始缓慢爬升,就能确认是进程内泄漏,这时该做的是把内存堆快照和相关日志留存给开发,而不是把重启频率调得越来越高。

重启的频率不要拍脑袋定。我一般的做法是看历史 RSS 曲线:基线 800M,每天涨 120M,机器 4G 内存,那么 12 天左右会触顶,重启周期定在 5 天比较安全,留一半余量应对业务波动。周期写到定时任务里,同时保留一个“可用内存低于阈值就提前重启”的兜底,两个条件取先到者。

3.3 cgroup 限额:让内核替你回收

比起定时脚本,更根本的做法是给服务设置内存上限,让内核在达到阈值时主动回收、触发 swap 或 OOM,而不是等到整机 available 见底。systemd 托管的服务可以直接在单元里写死。

# /etc/systemd/system/your-service.service.d/limit.conf [Service] # 软限:超过后内核开始积极回收该 cgroup 的页缓存 MemoryHigh=1536M # 硬限:达到后触发该 cgroup 内的 OOM,保护整机 MemoryMax=2G # 关闭 swap 依赖,避免内存被换出后掩盖泄漏 MemorySwapMax=0

MemoryHigh是节流阈值,走到这一步内核会优先回收这个 cgroup 的缓存,整机 MemAvailable 也不会被它拖崩。MemoryMax是保险丝,超过就杀,听起来暴力,但它把“整机不可用”换成了“单个服务被重启”,可控性强得多。MemorySwapMax=0只有在明确要暴露泄漏时才开,否则一次泄漏会把 swap 打满,整机 IO 先跪。

用 cgroup 限额的代价是要清楚服务的真实峰值,定低了会频繁 OOM,定高了等于没设。我的经验是按 P99 峰值乘 1.5,上线后盯一周的systemd-cgtop再微调。这套做下来,定时 drop_caches 往往可以退化成“极端兜底”,一个是防线,一个是创可贴,位置别搞反。

4. 定时任务落地:脚本、crontab 和 systemd timer 三件套

方案定下来之后,剩下的都是工程细节。同一件事在麒麟上至少有三种写法:裸 crontab、/etc/cron.d 下的配置文件、systemd timer。选哪个不重要,重要的是别让脚本在没人知道的情况下静默失败——定时任务最坑的地方不是不会写,而是写完之后你以为它在跑。

4.1 先写一个带阈值的回收脚本

不要写“每次执行都 drop”的脚本,那是在用性能换一个好看的监控数字。正确姿势是带上阈值判断,只有 available 真的低了才动手,顺便把每次判断结果落盘,方便事后核对它到底跑没跑、跑的时候是什么水位。

#!/bin/bash # /usr/local/sbin/mem-guard.sh # 用法: mem-guard.sh [阈值百分比],默认 15 set -u THRESHOLD="${1:-15}" LOG=/var/log/mem-guard.log # 一次 awk 取两个值,避免两次读 /proc/meminfo 之间数值漂移 read -r total avail < <(awk '/^MemTotal:/{t=$2} /^MemAvailable:/{a=$2} END{print t, a}' /proc/meminfo) # 整数百分比即可,避免 bc 依赖 pct=$(( avail * 100 / total )) stamp=$(date '+%F %T') echo "${stamp} available=${avail}kB total=${total}kB pct=${pct}% threshold=${THRESHOLD}%" >> "$LOG" # 水位健康,直接退出,不做任何回收动作 [ "$pct" -ge "$THRESHOLD" ] && exit 0 # 脏页先落盘,再做回收,避免回收过程阻塞在 IO 上 sync echo 1 > /proc/sys/vm/drop_caches logger -t mem-guard "dropped page cache, MemAvailable was ${pct}%" echo "${stamp} dropped page cache, was ${pct}%" >> "$LOG" # 极低水位额外记一条 warning,方便和监控告警对齐 if [ "$pct" -lt 5 ]; then logger -t mem-guard -p user.warning "MemAvailable ${pct}% is critical, check top RSS" fi

逐段拆一下。THRESHOLD="${1:-15}"让阈值可以从命令行传参,默认 15,这个值按机器实际情况改,4G 内存的机器 15% 大约是 600M,属于“还有余量但该管了”的位置。read -r total avail < <(...)用进程替换把 awk 的输出读进两个变量,比grep | awk | cut少几次 fork。pct=$(( avail * 100 / total ))是 bash 内建整数运算,不依赖 bc,这在最小化安装的系统上很关键。[ "$pct" -ge "$THRESHOLD" ] && exit 0用的是&&短路,水位健康就别碰内核。logger -t mem-guard把记录写进 syslog,-p user.warning是优先级,方便 rsyslog 单独分流到告警通道。

装的时候注意权限,脚本以 root 跑,普通用户可读就是隐患。

install -m 750 -o root -g root mem-guard.sh /usr/local/sbin/mem-guard.sh # 先手动跑一次,确认日志和数值都对 /usr/local/sbin/mem-guard.sh 15 && tail -3 /var/log/mem-guard.log

install -m 750一次把权限和属主都设好,比cp之后chmod少一步错。手动跑一次很重要——真实执行路径和 crontab 里的执行环境不同,先确认脚本本身逻辑没问题,再去查调度问题,能省掉大量来回。

4.2 crontab 写法与麒麟上的 crond 环境坑

麒麟这类 RPM 系的发行版用的是 crond 而不是 cron,服务名、日志位置都不一样。写任务之前先确认守护进程活着,这是后面所有排查的前提。

systemctl status crond --no-pager # 五个字段分别是 分 时 日 月 周 crontab -e
# crontab 内容 SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin # 每 5 分钟检查一次,flock -n 拿不到锁立即退出,避免上一轮没跑完就叠加 */5 * * * * /usr/bin/flock -n /var/run/mem-guard.lock /usr/local/sbin/mem-guard.sh 15 >> /var/log/mem-guard.log 2>&1

逐项说明。SHELL和PATH显式声明是因为 cron 启动的是非登录 shell,不会读 /etc/profile,默认 PATH 往往只有/usr/bin:/bin,脚本里一旦用到/usr/local/sbin下的命令就会“命令找不到”。*/5是步进写法,表示每 5 分钟。flock -n里的-n是 non-blocking,锁被占用就直接返回失败,这是防止脚本重叠执行最省事的办法,尤其在回收动作本身可能耗时几秒的情况下。结尾的>>和2>&1把标准输出和错误都追加到同一个日志,cron 默认会把这些内容当成邮件正文发出去,机器上没配 MTA 就是石沉大海。

还有一个高频坑:crontab 里的%是换行符,命令里带 date 格式化就会把任务截断,必须写成\%。这也是我倾向把逻辑全塞进脚本、crontab 里只留一行调用的原因。

验证的时候别只看crontab -l,要去看 cron 自己的执行日志。

# crond 每次拉起任务都会记一行,看有没有你的脚本 grep mem-guard /var/log/cron | tail -5 # 如果日志里连记录都没有,说明根本没触发,去查 crond 状态和文件权限 systemctl is-active crond

4.3 systemd timer 版本与日志落盘

比 crontab 更现代的做法是 systemd timer,好处是日志统一进 journald、可以声明依赖、可以对资源做限制,缺点是单元文件写起来比一行 crontab 啰嗦。

# /etc/systemd/system/mem-guard.service [Unit] Description=Drop page cache when MemAvailable is below threshold [Service] Type=oneshot ExecStart=/usr/local/sbin/mem-guard.sh 15 # 降低优先级,回收动作不和业务抢 CPU 和 IO Nice=10 IOSchedulingClass=idle
# /etc/systemd/system/mem-guard.timer [Unit] Description=Run mem-guard every 5 minutes [Timer] # 开机 3 分钟后首次触发,避开启动阶段的 IO 高峰 OnBootSec=3min # 之后每 5 分钟一次 OnUnitActiveSec=5min # 允许 30 秒误差,把多个定时器的时间点打散,减少同一秒的并发 AccuracySec=30s Unit=mem-guard.service [Install] WantedBy=timers.target

Type=oneshot表示这个服务跑完就退出,不需要常驻。OnBootSec和OnUnitActiveSec组合起来实现“开机后延迟启动 + 固定间隔”,比OnCalendar更适合这种高频短任务。AccuracySec很容易被忽略,默认值是一分钟,多个 timer 在同一分钟触发时会被内核合并唤醒,配上精度设置能错开。Nice=10和IOSchedulingClass=idle是给回收动作降权,避免它和业务争资源。

systemctl daemon-reload systemctl enable --now mem-guard.timer # 确认下次触发时间和上次执行结果 systemctl list-timers mem-guard.timer --no-pager # 看执行日志,oneshot 服务的输出都在这里 journalctl -u mem-guard.service -n 20 --no-pager

daemon-reload在改完单元文件后必须执行,漏掉的话 systemd 还在用旧内容,表现就是“明明改了却没生效”。list-timers输出里的 NEXT 和 LAST 两列是最有用的信息,NEXT 为空说明 timer 没被激活,LAST 是n/a说明从来没跑过。

5. 避坑清单:定时释放内存翻车的五个现场

下面五条都是我或者同事真踩过的,每条按现象、原因、解决三段写。看完再去配定时任务,能少走不少弯路。

5.1 脚本层面的三个坑:权限、并发、日志

第一条:手动执行正常,crontab 里毫无反应。

现象是终端里跑/usr/local/sbin/mem-guard.sh一切正常,日志也有,但挂到 crontab 之后一整天没动静。原因基本是环境差异:cron 用非登录 shell,PATH 缺/usr/local/sbin,工作目录是执行用户的家目录,脚本里任何相对路径都会失效。解决办法是把 PATH 显式写进 crontab 头部、脚本内所有路径全用绝对路径,并且把输出重定向到日志文件,这样至少能从日志看出它跑到哪一步。

第二条:回收太频繁,业务开始报慢查询。

现象是配了每分钟一次的 drop_caches 之后,数据库的慢查询数量翻了几倍,监控上内存确实变好看了。原因是页缓存和缓冲池被反复清空,每次读都要重新走磁盘,等于把内存压力换成了 IO 压力。解决办法是加水位阈值(低于 15% 才动)、把调度粒度放到 5 分钟、脚本内用flock -n保证不重叠,数据库机器上尽量只回收 1 不回收 2,避免 dentry 被清导致的路径查找放大。

第三条:跑了两周,/var 满了,服务反而挂了。

现象是某天监控报磁盘空间不足,排查发现/var/log/mem-guard.log涨到几个 G。原因是脚本每次执行都无条件追加一行,5 分钟一次一天就是 288 行,加上其他输出,长期无人清理。解决办法是给它配一条 logrotate,或者直接在脚本里做简单的体积控制。

# /etc/logrotate.d/mem-guard /var/log/mem-guard.log { weekly # 每周切一次 rotate 8 # 保留 8 份,约两个月 compress # 历史文件压缩 missingok # 文件不存在不报错 notifempty # 空文件不切 copytruncate # 先复制再清空,适合脚本用 >> 追加的场景 }

copytruncate是关键,脚本一直持有文件句柄往同一个文件追加,如果不加这个选项,rotate 之后进程还在往旧 inode 写,新文件永远是空的。

5.2 调度层面的两个坑:crond 没起、时间挤在一起

第四条:crontab -l里明明有任务,就是不执行。

现象是任务列表看得见,日志里一条执行记录都没有。常见原因有三个:crond 服务没设成开机自启,重启后根本没起来;任务写在/etc/cron.d/下但漏了用户名字段,格式不对被整行忽略;文件权限不是 644 或者文件名带了点号后缀,被 cron 直接跳过。解决办法是systemctl enable --now crond并确认is-active返回 active,/etc/cron.d/下的文件必须六段式(分 时 日 月 周 用户 命令),文件名只用字母数字和下划线。开了强制访问控制的机器,还要用getenforce看一眼状态,确认脚本路径没被策略拦住。

第五条:整点一到,机器集体卡顿。

现象是每天 0 点、每小时整点,负载和 IO 都会出现一个尖峰。原因是备份、日志切割、监控采集、加上这条回收任务,全都写在整点触发,几十个任务在同一秒醒来。解决办法是错峰,把回收任务的分钟位改成偏移值,比如3-59/5让它在 3、8、13 分触发,和整点任务错开。这只是调度层的调整,不用改任何业务代码,收益却很直接。

6. 十分钟定位法:从告警到根因的固定顺序

告警再响的时候,我一般不先看监控大盘,而是按固定顺序敲六条命令,十分钟内基本能定性。

free -h # 看 available,不看 used grep -E '^(AnonPages|SReclaimable|SUnreclaim|Shmem):' /proc/meminfo # 判断是进程占的还是内核缓存 ps -eo pid,rss,comm --sort=-rss | head -10 # 找头部进程 slabtop -o -s c | head -15 # 内核对象有没有异常增长 dmesg -T | grep -iE 'oom|killed process' # 历史上有没有被杀过 systemctl is-active crond; systemctl list-timers --no-pager | head # 定时任务本身还活着吗

判断逻辑可以压成一张表。

现象组合大概率根因下一步
MemAvailable 尚可,only used 高页缓存正常占用不改,调监控口径
MemAvailable 降,AnonPages 同涨进程泄漏留堆快照,定重启周期
MemAvailable 降,SUnreclaim 同涨内核对象泄漏查 slabtop 头部类型,找遍历型进程
Cached 高但 Shmem 占比大tmpfs 文件没清查 df -t tmpfs,清文件
available 够但申请大页失败内存碎片看 buddyinfo 高位,择机回收或重启

这套顺序的价值在于,它把“内存不释放”这个模糊描述拆成了互斥的几个分支,每一步都有明确的命令和判据,不会陷入“重启一下再看看”的循环。定时回收脚本在这个流程里只是最后一步的执行动作,前面五步才是决定该不该动手的依据。从那以后我每次上这类定时任务,都强制先跑一遍上面六条命令,把阈值写进脚本参数而不是拍脑袋定,日志和轮转也一起配好再上线。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/11/2 11:19:05

RK3588上手笔记:1、MobaXterm连接与串口接收解析

MobaXterm 选择: 波特率:`1500000` 数据位:`8` 停止位:`1` 校验:`None` 流控:`None` 也就是:`1500000-8-N-1`。野火 LubanCat-4 的 Debug 串口默认参数就是这个。 电脑必须接 3.3V USB-TTL 串口模块,才会出现 COMx。 板子上的 USB-C OTG 烧录口不能直接作为调试串口。 …

作者头像 李华
网站建设 2026/11/2 11:15:14

Java转AI Agent教程(第四周)整理骨架与首次接触

W4 教程&#xff1a;整理骨架 第一次接触 —— 从"我学过"到"我有东西"本周交付物&#xff1a;① 一个别人能直接用的骨架仓库&#xff1b;② 一次和 AI 团队负责人的对话。 验收线&#xff08;计划表原文&#xff09;&#xff1a;骨架能三行命令跑起来&a…

作者头像 李华