Linux进程管理核心:终止、等待与替换机制全解析
在 Linux 系统开发里进程管理可以说是最基础也最容易出问题的一环。很多同学写多进程程序时经常会遇到“子进程退出了但状态没回收”“想换一个程序跑结果 exec 失败了程序直接没”这类现象。这篇文章就围绕进程终止、进程等待和进程替换这三个核心概念把背后的机制、实现方式、坑点和实际代码一次讲透。我尽量用实际操作中的视角来写不是纯理论复读读过之后你至少能清楚进程退出时到底发生了什么、僵尸进程怎么避免、exec 族函数怎么正确使用以及这三个机制在实际项目里怎么配合。1. 进程终止进程的“告别”不只是退出1.1 三正常终止与两种异常退出你觉得一个进程是怎么结束的很多人第一反应是 main 函数里 return 0。但这只是最表面的形式。进程终止可以被分成典型的三类正常情况和两类异常情况。正常终止包括从 main 函数返回返回值就是退出码。调用 exit()这是标准 C 库提供的终止接口。调用 _exit() 或 _Exit()这是系统调用级别的终止接口。异常终止包括进程收到信号而终止比如 CtrlC 发送 SIGINT、非法访问内存触发 SIGSEGV。进程主动调用 abort()本质上是给自己发送 SIGABRT 信号。这里有个容易被忽略的细节从 main 返回其实等价于调用 exit()。因为 C 运行库会在 main 结束后执行一段收尾代码把返回值传给 exit()。你可以在自己的代码里验证比如在 main 后注册 atexit 回调它会执行这就说明 return 和 exit 走的是同一条路。区分“正常”和“异常”的关键在于正常终止总会执行用户态缓冲区的清理工作而异常终止是由内核直接回收资源。举个例子如果你在代码里写了 printf 但没有加换行然后直接调用 _exit()你会发现内容根本没有输出。原因就是 printf 的结果还在用户态缓冲区里_exit() 没有机会刷新它直接进内核了。这个点面试爱考实际开发中也是个容易踩的坑。1.2 exit 与 _exit 的区别缓冲区的故事用一张表来对比这两个接口对比项exit()_exit()所在层级C 标准库函数系统调用刷新 stdio 缓冲区会不会执行 atexit 注册的函数会不会关闭文件描述符由库函数负责收尾内核回收适用场景普通程序正常退出异常处理、紧急退出再说直白一点exit() 是礼貌地道别_exit() 是直接摔门走人。我在实际项目里见过一个很典型的 bug某个服务在接收到异常指令后调用了 exit() 试图退出但 exit 内部会执行一堆清理回调在清理过程中又碰到了共享资源的竞争条件导致退出流程卡死了。后来改成先用 _exit() 绕过用户态清理直接交还给内核问题立刻解决。1.3 exit 函数的参数与退出码的约定exit 函数的参数就是退出码。如果你在 main 里写 return 3Shell 里运行完执行 echo $? 就能看到 3。这个退出码在 Linux 里通常只有低 8 位是有效的取值范围 0-255。超出这个范围会被截断。业界约定0 表示成功非 0 表示失败。至于非 0 具体代表什么错误没有强制标准是你自己程序可以定义的。比如可以约定 1 是参数错误2 是文件不存在3 是权限不足。但需要注意的是很多通用工具会遵循一些常见惯例比如 1 表示一般错误2 表示误用 Shell 内建命令等。我的建议是尽早建立你自己的退出码规范表否则过三个月再看代码你自己都不记得退出码 17 是什么鬼。1.4 进程终止时的系统资源回收过程当进程真正终止时内核做的事情比你想象的多关闭该进程打开的所有文件描述符。释放进程的虚拟内存区域、页表。释放文件系统临时挂载、锁等资源。向父进程发送 SIGCHLD 信号通知状态变化。为子进程重新指定父进程通常是托付给某个系统进程。把进程的退出状态记录下来供父进程后续查询。注意最后一点进程并不是“消失得无影无踪”它会留下一个“尸体”等待父进程来收尸。如果父进程一直不来收这个“尸体”就变成僵尸进程。这就是为什么进程终止之后必须配套进程等待机制的原因。2. 进程等待给子进程“收尸”的正确姿势2.1 为什么必须等待僵尸进程与孤儿进程前面说了子进程终止后会留下退出状态等待父进程获取。如果父进程不去获取这个状态子进程的 task_struct 和部分资源就不能完全释放这个状态就是僵尸进程。僵尸进程的危害需要在实践中体会。它不占用 CPU也不占用大量内存但它占着进程表项。如果系统里有大量僵尸进程而进程表项被耗尽新进程就 fork 不出来了。我自己被这个问题搞崩过一次一个服务每秒钟 fork 一个子进程干活但父进程根本没调 wait几天之后整个机器 fork 失败所有服务开始连环报错重启才好。孤儿进程则是另一种情况父进程先死了子进程还没退出。内核会给这些孤儿进程找一个新父进程通常是某个系统级进程让它们不至于无人管理。孤儿进程本身不可怕真正麻烦的是它的输出和状态不再是原来的父进程能控制的了容易导致服务拓扑混乱。所以说父进程等待子进程不是可选的“礼貌”而是必须履行的责任。2.2 wait 和 waitpid 函数深度解析先看最简单的 wait#include sys/wait.h #include stdio.h #include stdlib.h #include unistd.h int main() { pid_t pid fork(); if (pid 0) { perror(fork); exit(1); } if (pid 0) { printf(子进程开始干活, pid%d\n, getpid()); sleep(2); exit(42); } int status 0; pid_t ret wait(status); printf(父进程回收了 pid%d, 返回值%d\n, ret, WEXITSTATUS(status)); return 0; }wait 的行为特点阻塞调用直到某个子进程退出才返回。只能回收任意一个子进程不能指定具体回收哪个。如果多次调用会逐个回收不同的子进程。waitpid 则灵活得多pid_t waitpid(pid_t pid, int *status, int options);pid 0等待指定 pid 的子进程。pid -1等待任意子进程等价于 wait。pid 0等待与调用者同进程组的任意子进程。pid -1等待进程组 id 等于 |pid| 的任意子进程。options 可以设置 WNOHANG表示非阻塞如果没有子进程退出立即返回 0。实际项目中waitpid 几乎是必用的因为你通常要精确控制某个子进程的退出状态。比如一个多进程任务池里某个 worker 挂了你希望马上感知到是哪一个从而只重启那一个而不是全部重启。用 wait 就会把信息搅混。2.3 用宏解析退出状态WIFEXITED、WEXITSTATUS、WIFSIGNALEDstatus 是一个编码值不是简单的退出码。你需要用宏来解析它。宏作用WIFEXITED(status)判断是否正常退出WEXITSTATUS(status)正常退出时获取退出码WIFSIGNALED(status)判断是否被信号终止WTERMSIG(status)被信号终止时获取信号编号WCOREDUMP(status)判断是否产生核心转储WIFSTOPPED(status)判断子进程是否处于停止状态WSTOPSIG(status)获取导致停止的信号我见过的典型错误直接 printf(%d\n, status); 然后发现打印出来的数字完全不是退出码。实际上 status 的低 8 位是信号相关高 8 位才是退出码你直接用 WEXITSTATUS 才是正解。还有一个容易忽略的点waitpid 返回 0 时WIFEXITED 等宏是不能用的因为根本没有状态可查。必须先判断返回值再判断宏。2.4 非阻塞等待与轮询模型来个实际可跑的非阻塞等待示例#include sys/wait.h #include stdio.h #include stdlib.h #include unistd.h int main() { pid_t pid fork(); if (pid 0) { sleep(5); exit(7); } int status 0; pid_t ret 0; while (ret 0) { ret waitpid(pid, status, WNOHANG); if (ret 0) { printf(子进程还在跑, 先做点别的事情...\n); sleep(1); } } if (ret 0) { printf(回收成功, 退出码是 %d\n, WEXITSTATUS(status)); } return 0; }在轮询循环中每次 WNOHANG 返回 0说明目标子进程仍在运行你就可以趁机处理其他逻辑。很多人会问waitpid 返回 -1 且 errno 是 EINTR 怎么办这说明系统调用被信号打断了如果你还想继续等应该再次调用。处理方法是包一层循环判断 errno 做出对应的重试或跳出。3. 进程替换换一个程序运行同一份躯体3.1 exec 族函数的整体地图进程替换的原理核心就一句话当前进程“我不用原来的代码了我换一套新的程序镜像来执行”。注意进程 PID 不变文件描述符多数情况下不变变的只是代码段、数据段、堆和栈。exec 族函数就是干这个的。函数名是否用 PATH 搜索参数形式是否传环境变量execl否列表继承当前环境execv否数组继承当前环境execlp是列表继承当前环境execvp是数组继承当前环境execle否列表 envp指定环境execve否数组 envp指定环境函数名的记忆口诀我自己的版本只要带 l 的就是传列表带 v 的就是传数组带 p 的就是会去 PATH 环境变量里找程序带 e 的就是可以自定义环境变量。这样一看就分清了。3.2 exec 函数带不带 p 的影响很多人不理解为什么 execl 和 execlp 的行为不同。区别在于不带 p 的函数不会去 PATH 里搜索你传的路径必须是真的路径带 p 的函数如果传入的文件名不带斜杠会自动到 PATH 环境变量指定的目录里去遍历查找。实际应用中带 p 系列用起来更方便比如在 Shell 实现里你不需要自己去拼接一个绝对路径让 execvp 去搜索就够了。但需要注意的是带 p 的函数在找不到程序时会返回错误你需要感知到这个错误并做相应处理比如提示命令不存在。如果不带 p路径写错了大概率是崩溃或者返回 ENOENT。补充一个细节exec 函数什么事都没做成功才会返回。只要 exec 调用成功原进程的代码就再也没有回来执行的机会了。所以 exec 后面如果还写了代码那这段代码只会在 exec 失败时才执行。这就是为什么所有 exec 调用的返回值检查都极其重要。3.3 exec 与 fork 的经典配合套路因为 exec 会替换当前进程镜像所以如果只想替换一个子进程、让父进程继续干自己的事就要先 fork然后在子进程里 exec。这也是所有 Shell 执行外部命令的底层套路。#include sys/wait.h #include stdio.h #include stdlib.h #include unistd.h int main() { pid_t pid fork(); if (pid 0) { perror(fork); exit(1); } if (pid 0) { execlp(ls, ls, -l, NULL); perror(execlp); exit(1); } int status 0; waitpid(pid, status, 0); if (WIFEXITED(status)) { printf(子进程退出码: %d\n, WEXITSTATUS(status)); } return 0; }子进程里 exec 失败之后务必要 exit 出来否则子进程会继续执行父进程残留的代码造成双份逻辑运行这是新手最常犯的错。我见过一个案例exec 失败后没有 exit结果子进程跑去执行了父进程后续的数据库写入逻辑把生产库的数据搞乱了。这种故障排查起来极其痛苦因为表面症状完全不像 exec 的问题。3.4 应用场景Shell、服务热更新与容器进程替换最有价值的应用场景之一是热更新。比如一个服务进程它想在不退出、不丢端口监听的情况下重新加载新的代码逻辑。做法是先 fork 一个子进程让子进程继承父进程已经 listen 的文件描述符再 exec 新的二进制新的代码继续监听同一个端口。这种技术在优雅重启类工具里很常见核心原理就是 fork exec 保留了文件描述符。Shell 里的管道实现也是类似逻辑fork 出左端命令的进程fork 出右端命令的进程分别 exec通过 pipe 连起来。可以说shell 的很多机制都建立在进程替换之上。进程替换并不是一个孤立的话题它是所有多进程操作系统的核心行为模型。4. 综合实战进程池模型里的三个机制4.1 从概念到进程池为什么要把三件事放一起单个的进程终止、进程等待、进程替换学起来都感觉不难。但到了真实项目中三件事往往是交织在一起的。这里我以一个多进程任务池为例展示三者如何协同。进程池的思路父进程创建多个子进程每个子进程专门处理任务。子进程在任务间隙休息需要干活时被分配任务。一旦子进程异常退出父进程要感知到并补充新子进程。补充新子进程时可以用 fork exec 执行一个独立的 worker 程序。4.2 进程池代码与运行效果#include sys/wait.h #include stdio.h #include stdlib.h #include unistd.h #include string.h #define WORKER_NUM 3 void do_worker_loop() { for (int i 0; ; i) { printf(worker %d 处理第 %d 个任务\n, getpid(), i); if (i 2) { exit(10); } sleep(1); } } int main() { pid_t workers[WORKER_NUM]; for (int i 0; i WORKER_NUM; i) { pid_t pid fork(); if (pid 0) { perror(fork); exit(1); } if (pid 0) { execlp(./worker, worker, NULL); perror(execlp); exit(1); } workers[i] pid; } while (1) { int status 0; pid_t ret waitpid(-1, status, 0); if (ret 0) { int code WIFEXITED(status) ? WEXITSTATUS(status) : -1; if (WIFSIGNALED(status)) { code WTERMSIG(status); } printf(父进程发现 worker 退出 ret%d code%d\n, ret, code); pid_t new_pid fork(); if (new_pid 0) { execlp(./worker, worker, NULL); perror(execlp); exit(1); } printf(父进程创建了新 worker%d\n, new_pid); } } return 0; }不过上面代码里的 worker 段涉及 execlp 加载同一个文件实际测试时可把 worker 逻辑直接写在子进程分支里。真实的工程里worker 多是一个独立编译的程序通过 exec 加载进来特点就是父进程代码和 worker 代码解耦哪怕 worker 崩溃也不影响父进程的稳定性。4.3 为什么 exec 失败要单独处理前面已经反复提过再强调一次exec 失败后子进程并没有被替换它还是原来那套逻辑。如果你不写 exit(1)它会继续执行父进程的剩余代码而那个上下文里往往包含父进程的核心业务逻辑。假设父进程是一个数据库服务子进程又恰好继承了数据库连接句柄那它就会成为一条失控的“分身”可能造成多个进程同时操作同一批数据。这种事在真实故障里并不罕见所以 exec 后的 exit 不是可有可无的细节而是安全底线。4.4 从退出状态到故障感知signal 与 waitpid 的组合在实际的多进程服务里光靠阻塞的 waitpid 是不够的。更常见的做法是父进程收到 SIGCHLD 信号后在信号处理函数里调用 waitpid 回收子进程从而及时发现 worker 的退出。SIGCHLD 可以被设置成 SIG_IGN这时候内核会自动回收子进程不让它变成僵尸。但代价是你无法再通过 waitpid 获取具体的退出状态。我的建议是如果只是简单场景可以忽略 SIGCHLD 让内核自动回收如果需要精确管理子进程状态还是老老实实写信号处理逻辑在 handler 里用 waitpid 配合 WNOHANG 回收全部已退出的子进程。5. 常见问题与排查技巧实录这些坑我替你踩过5.1 子进程退出码大于 255 会发生什么退出码的存储空间只有 8 位。如果程序 exit(300)实际记录到的是 300 % 256 44。这不是 bug是系统设计。所以设计退出码规范时建议只用 0-125 区间留一些余量不要定义到大数值否则代码移植到不同平台上可能让你怀疑人生。5.2 waitpid 返回 -1 时你真的看 errno 了吗waitpid 返回 -1 有三种常见情况errno含义处理方式ECHILD已经没有子进程可等待检查业务逻辑避免无意义等待EINTR被信号打断重新调用 waitpid 继续等待EINVAL参数错误检查 options 和 pid 传参是否合法很多人碰到 waitpid 返回 -1 就只会打印 perror但 EINTR 这个情况特别容易漏。生产环境中如果父进程注册了一些定时信号EINTR 会频繁出现你不处理它worker 退出信息就可能丢。5.3 僵尸进程的清除顺序当你发现系统里出现大量僵尸进程别慌先观察如果僵尸进程的父进程是服务说明服务代码没调 waitpid 或者 waitpid 位置写错了。如果父进程已经是某个系统进程那就说明服务本身早就崩了僵尸被托管了。清除僵尸进程的正规手段是修复代码让父进程正确调用 wait。临时手段是重启父进程让内核重新托管并最终回收僵尸。但千万别想着 kill -9 僵尸进程僵尸进程是杀不掉的因为它已经不是“活”的进程了。5.4 exec 后文件描述符泄漏问题exec 之后默认情况下原有的文件描述符是保留下来的。如果不加管控一个进程中打开了一个日志文件fork exec 之后子进程也持有这个日志文件描述符如果双方都往里写日志顺序就全乱了。常规做法是在 exec 前把不需要的 fd 设置成 FD_CLOEXEC使 exec 时自动关闭。这是在真实开发中很容易被忽视的细节。经验法则所有在新程序里不该用到的文件描述符都要打好 close-on-exec 标记。否则你排查一个“这个文件为什么被莫名打开”的诡异问题时会浪费大量时间。5.5 子进程状态查询的常用速查表需求用什么等任意一个子进程退出wait 或 waitpid(-1)等指定子进程退出waitpid(pid)非阻塞检查waitpid(pid, status, WNOHANG)同时回收多个已退出子进程循环 waitpid(-1, WNOHANG)获取退出码WEXITSTATUS(status)判断是否被信号杀死WIFSIGNALED(status)判断是否生成 coreWCOREDUMP(status)5.6 为什么 exec 后进程 PID 没变这个一定要想明白。exec 只是把当前进程的地址空间替换成新的程序镜像进程的 PID 是内核调度的标识不会因为换了程序而改变。所以 exec 后 getpid() 还是原来的值。这一点在写服务和做监控时尤为重要。如果按 PID 区分模块行为exec 后要重新依据程序名来做判断不要把 PID 当成“当前运行的是哪段代码”的标志。5.7 fork 和 exec 组合时父进程等待的必要性有些人会想既然 worker 自己会退出为什么父进程要管问题在于父进程不管子进程会变成僵尸。僵尸进程累积到一定量fork 会失败这会导致你无法再创建新 worker系统像踩了刹车一样慢慢失去响应。更可怕的是这类故障往往不报明显错误只是日志里反复出现 “Resource temporarily unavailable”。如果你看到这个报错先查进程表看看是不是僵尸进程爆了。5.8 多线程进程中 fork 的隐藏风险多线程程序里调用 fork 要尤其小心。一个进程内多个线程其中某个线程调用了 fork那么子进程里只会有当前这一个线程其他线程都消失了。如果之前某个线程持有了锁而该锁在子进程里不再被释放就会死锁。印象里某一年线上故障就是产品内部一个多线程应用其中一个线程 fork 一个子进程去跑脚本子进程里恰好要分配内存而内存分配器内部锁被死锁整个子进程卡住。这个坑在复杂多线程程序里非常普遍做设计时一定要对 fork 场景有所预料。5.9 调试进程等待类问题的通用工具排查进程退出问题常用的控制台工具有ps -o pid,ppid,stat,cmd查看进程状态标识Z 就是僵尸。top 里的 STATE 字段观察实时进程状态。strace跟踪系统调用能看到父进程调用 waitwaitpid 的次数。pstree查看进程树结构确认父子关系。strace 这个工具在排查 waitpid 问题时尤其犀利。如果你不确定服务有没有调 wait直接跟踪它的系统调用一清二楚。写在最后我的一点实际体验我在实际开发中学到的一件事进程管理最怕的不是不懂 API而是没有提前想清楚状态流转。进程终止、等待、替换三者在设计阶段就该有明确的预案。比如每个子进程退出后由谁回收是在信号处理里还是主循环里如果 worker 异常退出是重启还是整体退出exec 失败要不要触发告警。这些事情等到线上出了故障再想就已经晚了。另一条建议是写多进程代码时先画一张状态变化表把父进程和子进程各自的状态列清楚再动手写代码。这张表不需要几步就能避免大部分进程管理相关的低级问题。如果你在自己的项目里按这个思路走一遍应该能感受到这三个机制是如何环环相扣、缺一不可的。

相关新闻

LangChain API暴露危机:5个Docker安全配置漏洞自查清单

LangChain API暴露危机:5个Docker安全配置漏洞自查清单

先说个让我印象很深的事。某团队给内部知识库做了一个基于LangChain的问答服务,容器一跑起来就直接对外开放。结果没撑过一周,大模型API费用报警,账单比预算超了十倍。查下来发现,不是业务量涨了,而是他们部署LangChai…

2026/10/18 6:08:48 阅读更多 →
基于主从博弈的小区电动汽车充电动态定价策略优化

基于主从博弈的小区电动汽车充电动态定价策略优化

我先把这个项目标题拆开看了一遍:智能小区、电动汽车充电、代理商动态定价、主从博弈、策略优化。这五个词组合起来,对应的核心问题就一句话——小区充电这件事,代理商的定价行为和用户充电行为存在明显的先后响应关系,而这种关系…

2026/10/18 6:08:48 阅读更多 →
云本结合AI桌面客户端:解决办公最后一厘米割裂感

云本结合AI桌面客户端:解决办公最后一厘米割裂感

1. 项目概述:这不是一个普通客户端更新,而是一次工作流重构的落地信号“XXL-AI v1.1.1 发布|Desk 桌面客户端正式上线,云本结合再进一步”——这个标题里藏着三个被多数人忽略但极其关键的信号词:“Desk”、“桌面客户…

2026/10/18 6:08:48 阅读更多 →

最新新闻

机器学习大作业实战指南:从数据清洗到模型调优的完整流程

机器学习大作业实战指南:从数据清洗到模型调优的完整流程

简介:这份资源是电子科技大学机器学习课程大作业的完整配套资料,面向正在修读机器学习、人工智能相关课程的高校学生,以及希望系统梳理算法理论与工程实践的自学者。内容围绕监督学习、无监督学习、半监督学习与强化学习等范式展开&#xff0…

2026/10/18 6:57:58 阅读更多 →
高德地图JS API结合Loca实现3D动画的实战指南与性能优化

高德地图JS API结合Loca实现3D动画的实战指南与性能优化

做地图可视化这么多年,我一直觉得高德JS API里最被低估的模块就是Loca。早期在某中央商务区大屏项目里,需要在底图上展示几千栋楼宇的数据密度,我一开始用Marker逐栋添加,数据一上三百个页面就开始掉帧,滚动一下地图卡…

2026/10/18 6:57:58 阅读更多 →
SILENTTRINITY模块开发实战:用Boo语言编写后渗透侦察模块

SILENTTRINITY模块开发实战:用Boo语言编写后渗透侦察模块

“SILENTTRINITY”这个词,我在好几年前第一次看到时,第一反应是“又一个 C2 框架”。真正上手用了一个星期后,我改变了对它的看法——它最大的亮点不是通信方式多花哨,而是模块扩展机制:用 Boo 语言写后渗透模块。你不…

2026/10/18 6:57:58 阅读更多 →
Redis命令:RPOP

Redis命令:RPOP

Redis RPOP 命令详细教程 RPOP 移除并返回列表表尾(右侧)的最后一个元素,与 LPOP 恰好方向相反,是列表作为队列、栈使用时另一种常用的"出队"命令。它自 Redis 1.0.0 起提供,从 6.2.0 起支持可选的 count 参…

2026/10/18 6:57:58 阅读更多 →
网络工程师面试核心:从协议原理到工程直觉的五层穿透

网络工程师面试核心:从协议原理到工程直觉的五层穿透

1. 为什么“舌战面试官”不是嘴炮,而是网络工程师的生存基本功“舌战面试官——计网篇(一)”这个标题乍看像段子,实则戳中了无数求职者最真实的痛感。我带过不少刚毕业的某高校网络方向学生,也辅导过转行做后端但卡在O…

2026/10/18 6:57:58 阅读更多 →
多智能体监控与治理:构建云上AI劳力工厂的实用指南

多智能体监控与治理:构建云上AI劳力工厂的实用指南

最近圈子里都在聊“云上劳力工厂”这个概念——把一群 AI 智能体部署到云端,像流水线工人一样自动执行任务,而管理者只需要在中控台盯着一块大屏,看它们谁在干活、谁卡住了、谁在摸鱼烧钱。某 AI 实验室放出的这套方向很有意思:它…

2026/10/18 6:56:58 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →