Linux进程切换与环境变量:从原理到排错实践
1. 从一段“卡顿”说起为什么进程切换值得我们死磕先抛个场景。你在终端里同时开着编译任务、一个网页服务、还有编辑器系统看起来“同时”在跑所有东西。但只要你做过性能分析或者写过对延迟敏感的程序你一定被下面这类问题折磨过为什么我的服务偶尔会抖一下耗时突然飙到几十毫秒为什么我在脚本里 export 了一个变量子进程就是读不到这两件事答案其实都藏在 Linux 进程的两个核心机制里——进程切换和环境变量。进程切换决定了你的程序在 CPU 上“怎么被换进换出”环境变量决定了“子进程从父进程那里继承了什么样的运行上下文”。很多人学 Linux 进程背了一堆 API知道 fork、exec、exit但一到实际排查问题就抓瞎本质上就是这两块没打通。这篇我打算把进程切换的完整链路拆开揉碎讲清楚从时间片、调度器到上下文切换的每一步开销来源再深入环境变量的存储位置、继承规则、修改生效的层级关系最后用一组实际问题的排查过程把它们串起来。内容适合正在学系统编程的开发者、做服务端性能优化的同学以及所有被“进程行为诡异”困扰过的运维和后台开发。我自己最早接触这两块内容时也是被各种术语绕晕过内核态、用户态、寄存器组、栈指针、全局区、栈区……后来发现与其死记概念不如从“一次进程切换到底发生了什么”出发把每一个环节当作一条执行路径去理解。下面进入正题。2. 进程切换一次“换人”背后的完整动作序列2.1 从时间片说起为什么需要切换先明确一个基本前提一个 CPU 核心在任意时刻只能执行一个进程的指令。但我们日常使用电脑感觉所有程序都在同时跑。这不是魔法而是操作系统把 CPU 时间切成了一段段很短的时间片轮流分配给各个进程。时间片一到当前进程就得让位下一个进程上场。这个“让位”和“上场”的过程就是进程切换。类比一下你只有一个工位但有十个项目要推进。你不可能同时坐在十个工位上写代码所以只能每隔一段时间换一个工位。每次换工位你都要停下来记住当前项目写到了哪个文件哪一行保存现场然后走到另一个工位翻出那边之前的笔记恢复现场继续写。如果你记性不好每次换工位还要重新翻半天资料那大部分时间其实都耗在“换”本身而不是“写”上了。进程切换也是同理——切换本身是有开销的而且这个开销在很多场景下是你性能瓶颈的隐藏推手。能触发切换的事件主要有这么几类时间片耗尽这是最常见的进程自己主动让出 CPU比如调用 sleep 或等待 I/O有更高优先级的进程就绪比如你敲了一下键盘处理输入的高优先级任务需要立刻插队以及进程退出或被杀死。理解这些触发条件对你设计程序的行为模型很有帮助。比如某个进程大量忙于计算不主动让出 CPU它就更容易被时间片打断切换开销占比自然就高。2.2 切换时到底保存了什么寄存器与上下文很多人以为进程切换就是“内存里换个指针”大错特错。切换的核心是保存和恢复“上下文”而上下文的定义极其具体——它就是 CPU 那一堆寄存器里的值外加程序计数器、栈指针、状态寄存器以及内存管理的相关信息。寄存器是 CPU 内部的高速存储单元指令操作的数据几乎都要经过它们。想象你正在算一道复杂的算式笔算时步骤写到一半草稿纸上的中间结果就是“寄存器”。换一道题做之前你必须把中间结果另存一份否则回来时什么都想不起来。进程切换时当前进程在寄存器里的所有中间结果都必须原样保存到它的进程控制块PCBProcess Control Block里等这个进程再次被调度上场时再把保存的值原样装回寄存器。这个“保存到 PCB”和“从 PCB 恢复”的动作就是上下文切换的核心动作。需要特别指出的是进程切换涉及用户态和内核态的转换。进程平时跑在用户态但一旦触发切换必须经由内核调度器完成所以会先陷入内核态再切走。这意味着切换不仅涉及寄存器存取还伴随用户态和内核态之间的栈切换、权限级别切换。如果你用 perf 或者 strace 观察过一个频繁切换的进程你会看到大量时间其实耗在内核的调度路径上。我给一个实操建议如果怀疑进程切换开销过大可以直接看/proc/pid/status里的 voluntary_ctxt_switches 和 nonvoluntary_ctxt_switches 两个字段。前者是进程主动让出 CPU 的次数比如等 I/O后者是被抢占的次数时间片耗尽或被更高优先级打断。两个数字都高说明切换很频繁这时候要看是不是进程模型设计有问题而不是盲目调大并发。2.3 调度器的决策逻辑切换不是随机的进程切换的“调度权”在内核调度器。Linux 默认的调度器是 CFS完全公平调度器Completely Fair Scheduler它的核心思路是维护一个红黑树按照每个进程的虚拟运行时间排序每次选虚拟运行时间最小的进程上 CPU。所谓虚拟运行时间是实际运行时间经过优先级加权后的值——优先级高的进程同样跑 1ms虚拟时间增长得慢所以它更容易被选中。这套设计解决了“公平”和“优先级”的统一问题。你在写多进程程序时不需要直接操作调度器但有几个点会影响调度行为进程优先级nice 值、调度策略比如实时调度策略 SCHED_FIFO、SCHED_RR 和普通策略 SCHED_OTHER、以及 CPU 亲和性affinity。其中 CPU 亲和性容易被忽略——如果把进程绑定到特定 CPU 核心可以显著减少缓存失效带来的切换成本。我用 taskset 命令给高吞吐的进程绑定核心后确实看到过性能提升尤其是频繁访问共享数据的场景。这里有个常见的认知误区不是说越多的进程并行就越好。进程越多切换越频繁缓存越容易失效有效计算率反而下降。这就是为什么某些高性能服务宁愿用线程池、固定数量 worker也不愿意无脑 fork 一堆进程。你多开几个进程表面上“并行”了但如果它们抢同一个 CPU结果就是频繁切换、互相拖累。3. 上下文切换的开销账本看不见的性能杀手3.1 开销从哪来不只是保存寄存器上下文切换的开销很多人以为只是保存恢复寄存器那几十条指令。实际上现代 CPU 下最大的开销来自缓存失效。每个进程都有自己独立的虚拟地址空间。进程 A 切到进程 B意味着 CPU 要切换页表也就是切换地址映射关系。一旦页表切换TLBTranslation Lookaside Block页表缓存基本就废了所有后续的内存访问都要重新走页表查询。同时L1、L2、L3 缓存里的数据虽然物理上还在但逻辑上很多是进程 A 留下的对进程 B 来说是无效的需要慢慢重新填充。这两个后果叠加起来切换之后的一段时间里程序运行效率是打折扣的。我实测过一个数据密集型任务的模拟场景进程内多线程并发时因为线程切换不需要切换页表线程共享地址空间整体吞吐比多进程模式高了大约 20%~30%。这就是为什么很多服务端程序推崇多线程而非多进程。多线程也有切换但开销小一个量级。多进程的优势是隔离性好某个进程崩溃不会拖垮全部但代价就是上下文切换更重。额外说一句近年流行的协程比如 goroutine、Python 的 asyncio本质上就是把“切换”从内核态搬到了用户态由用户程序自己控制何时让出。协程切换不需要陷入内核、不需要切换页表代价可能只是切换几个寄存器和栈指针所以能支撑极高的并发。理解了内核态进程切换的成本你就能明白协程为什么能做成“十万甚至百万并发”的噱头了。3.2 实际测量怎么量化切换开销写代码时如果你想知道系统当前上下文切换的整体情况可以看/proc/stat里的 ctxt 字段它记录了系统自启动以来的上下文切换总数。想看动态变化可以用vmstat 1其中的cs列就是每秒上下文切换次数。我遇到过一台机器cs 值轻松飙到几十万但 CPU 利用率并不高排查下来是某个程序疯狂创建短命进程把系统拖进了切换风暴。这种情况优化方向不是调参而是改代码逻辑比如用线程池代替频繁 fork。做微基准测试时会用到perf stat这样的工具看 context-switches 事件。不过需要注意的是测量本身会影响结果因为 perf 也会触发调度。更实用的经验是先看趋势再看绝对数值。只要切换次数从几千涨到几十万不管绝对开销多大你都得警惕了。4. 环境变量每个进程出生时自带的“初始设置”4.1 环境变量长什么样、存在哪讲完切换进入第二个主题环境变量。它其实就是一组键值对比如PATH/usr/local/bin:/usr/bin、HOME/home/user。这些键值对在进程启动时被复制到进程自己的内存空间里在进程生命周期内可以被读取和修改。关键点是环境变量不是全局共享的而是每个进程私有的一份拷贝。你在一个终端里 export 一个变量另一个终端里的进程是感知不到的。因为它只是那个 shell 进程自己环境变量表里的一个条目shell 启动子进程时会按需把这份表复制给子进程。很多人第一次接触这个知识点时会纳闷export 之后不是全局生效了吗其实只是“当前 shell 及其后续启动的子进程”生效。理解这一点很多环境变量相关的困惑就能迎刃而解。它在内存里位于进程地址空间的什么位置呢具体来说在 Linux 上环境变量和命令行参数一起存放在进程用户态栈的顶部区域。内核在 exec 加载新程序时会把环境变量和参数按特定布局压到新进程的栈上。这也是为什么main函数能拿到envp这个参数——它就是指向这块区域的指针。4.2 继承机制子进程如何拿到父进程的环境变量进程创建流程是 fork exec。fork 时子进程几乎完整复制了父进程的内存镜像包括环境变量区exec 时新程序映像加载进来但环境变量区一般会被保留并重新整理。所以最终效果是子进程完整继承了父进程的环境变量。但这个继承不是无限的“隔代遗传”它只发生在父子关系链上。A 启动 BB 启动 CC 能拿到 A 的环境变量吗能前提是 A - B - C 这条链上每一环都没有把变量删掉或覆盖。也就是说环境变量的传递是线性的、逐层复制的。如果中间某个环节的进程自己unsetenv了某个变量后续子孙进程就再也看不到了。这带来一个很实用的排错思路如果你发现某个子进程拿不到预期的环境变量不要只检查启动它的那个 shell要顺藤摸瓜查整条进程链。比如你用 systemd 管理服务systemd 里配置的环境变量会传给服务进程但如果你在服务内部又 fork 了子进程那些子进程继承的是服务进程的环境变量而不是 systemd 的。我曾经做过一个数据采集服务子进程报错说连不上数据库排查半天发现是父进程里 DSN 环境变量被某个库函数给改了子进程继承的是被改过之后的值。4.3 修改环境变量的几个层级别搞混修改环境变量有多个层面从低到高分别是内核/系统层比如/etc/environment、shell 启动文件层比如~/.bashrc、/etc/profile、当前 shell 会话层export、以及进程内部代码层setenv。/etc/environment是系统级的环境变量定义登录时会被读取但它一般只支持简单的KEYvalue格式不支持变量展开和逻辑判断适合放纯静态配置。shell 启动文件是大多数人修改 PATH 的地方。注意不同 shell、不同登录方式加载的文件不一样交互式登录 shell 会读/etc/profile和~/.bash_profile非登录交互式 shell 读~/.bashrc。改完文件后要么重新登录要么source一下才能生效。当前 shell 会话层的 export只对当前会话和它后续启动的子进程生效关掉终端就没了。进程内部代码层的修改只影响当前进程和它后续 fork 的子进程。这四个层级容易出问题的地方是你在一个脚本里 export 了变量但脚本跑完了变量随之消失——因为脚本本身就是一个子进程它的 export 只影响它自己影响不到启动它的父 shell。这也是我最常被问到的问题之一“我在脚本里 export 了为什么外面没有”。答案就是层级关系没理清。5. 实操从进程创建到环境变量传递的完整实验5.1 实验一fork 后的变量独立性验证空谈容易忘动手一次就记住了。我建议你做一个简单的实验来验证环境变量是“进程私有拷贝”这一特性。先用 shell 写个小脚本test_env.sh#!/bin/bash export MY_TEST_VARfrom_parent echo 父进程 PID$$, MY_TEST_VAR$MY_TEST_VAR bash -c echo 子进程 PID$$, MY_TEST_VAR$MY_TEST_VAR; export MY_TEST_VARchanged_by_child; echo 子进程修改后: MY_TEST_VAR$MY_TEST_VAR echo 回到父进程: MY_TEST_VAR$MY_TEST_VAR运行它观察输出。你会发现子进程修改MY_TEST_VAR后父进程里读到的还是原来的值。这就是“复制”而非“共享”的直观证据——如果环境变量是共享的父进程读到的值也应该变化。再用 C 语言做一次加深理解#include stdio.h #include stdlib.h #include unistd.h int main() { setenv(MY_VAR, original, 1); printf([%d] before fork: MY_VAR%s\n, getpid(), getenv(MY_VAR)); pid_t pid fork(); if (pid 0) { // 子进程 setenv(MY_VAR, child_modified, 1); printf([%d] child: MY_VAR%s\n, getpid(), getenv(MY_VAR)); _exit(0); } else { // 父进程等待子进程结束后再看 wait(NULL); printf([%d] after child exit: MY_VAR%s\n, getpid(), getenv(MY_VAR)); } return 0; }编译运行父进程最后打印的依然是original。这个实验几十行代码但比任何文档都直观。5.2 实验二exec 后环境变量的去向fork 实验验证的是“复制”接下来验证 exec 是否保留环境变量。一个小 C 程序 exec 一个外部命令同时传入自定义环境变量#include stdio.h #include unistd.h #include stdlib.h int main() { setenv(MY_SECRET, hello_world, 1); char *envp[] {MY_SECREThello_world, NULL}; char *argv[] {/usr/bin/env, NULL}; printf(调用 exec 前: MY_SECRET%s\n, getenv(MY_SECRET)); // execve 使用 envp 传入完整的环境变量数组 execve(/usr/bin/env, argv, envp); // exec 成功的话不会走到这里 perror(execve failed); return 1; }/usr/bin/env会把当前环境变量全部打印出来你能看到MY_SECRET确实传进去了。这里要注意execve的第三个参数 envp 会整体替换环境变量表而execle/execvpe等函数行为略不同。如果你用execvp不传 envp子进程会继承父进程的environ。从实操角度看exec 系列函数里最容易踩的坑是想给子进程单独设置几个环境变量但不小心把父进程的整个环境变量表覆盖了。解决办法是先读父进程的environ修改或追加后再传给 execve。很多封装了 exec 的库函数就是这么干的。5.3 实验三进程切换开销的观测环境变量验证完之后回到进程切换给一个观测方法。写一个简单的死循环程序让它跑满 CPU看它的上下文切换情况# 用 dd 从一个文件读数据到另一个文件会触发大量 I/O 等待和切换 # 或者直接用 stress-ng 模拟 stress-ng --cpu 1 --timeout 10s # 找到 pid PID$(pgrep -f stress-ng --cpu | head -1) # 查看自愿/非自愿切换 cat /proc/$PID/status | grep -E voluntary_ctxt_switches|nonvoluntary_ctxt_switches第一次看时你会惊讶一个纯计算程序也有不少非自愿切换因为时间片会被反复耗尽。如果这个数字非常大说明系统的 CPU 资源紧张或者进程优先级太低总是被别的进程抢走 CPU。换个场景如果你运行一个频繁 sleep(0.001) 的程序自愿切换次数会飙升——它每次 sleep 都会主动让出 CPU。这两种切换的次数比例能帮你定位程序是 I/O 密集型还是 CPU 密集型。6. 实战排错环境变量“失效”的典型问题与解决6.1 案例一脚本里 export 了但外面读不到这是最常见的问题前面已经提到成因。某同学写了个部署脚本deploy.sh里面 export 了数据库地址跑完之后在终端里 echo 却为空。原因就是脚本在子 shell 里运行export 只影响脚本自身。解决办法有两个方向一是用 source 执行脚本.或source deploy.sh让脚本在当前 shell 里执行二是让脚本把环境变量写到一个文件里父 shell 再去 source 这个文件类似很多云平台的做法。我见过最笨但最有效的封装方式# 在 deploy.sh 最后生成环境文件 cat .env_export EOF export DB_HOSTxxx export DB_PORT5432 EOF使用方执行source .env_export。这种方式的好处是显式、可控比盲目 source 整个脚本要安全因为脚本里可能有其他副作用。6.2 案例二systemd 服务里环境变量丢失用 systemd 管理服务时你经常需要配置环境变量。常见写法是在 service 文件里加[Service] EnvironmentAPP_ENVproduction EnvironmentFile/etc/myapp/env.conf但如果你同时在~/.bashrc里配置了变量然后又在 shell 里手动启动同一个程序会发现环境变量不一致——因为 shell 启动时加载的变量systemd 环境里根本没有。反之亦然。这个坑很容易让人怀疑是代码 bug实际是环境变量来源不同。我的建议是对于生产服务所有环境变量都集中到 service 文件或 EnvironmentFile 里管理显式声明、可审计不要依赖 shell 的登录脚本。调试时可以临时用systemctl show查看服务的环境变量配置确认它确实拿到了预期的变量。6.3 案例三父进程污染的传递还有一种隐蔽的问题父进程在运行过程中自己改了环境变量导致子进程继承了“被污染”的值。比如某个第三方库内部调用了 setenv把 LD_LIBRARY_PATH 给改了后续 fork 出的子进程就全带着这个值。遇到这种情况我习惯在 fork 前打印一份完整的environ用一个临时转储文件对比前后差异定位是谁改的。用gdb也可以在 setenv 处打断点但成本高一些经验不足时先从转储文件找线索更高效。另外某些语言运行时比如 Java、Go在启动时也会调整环境变量如果你从这些程序里再启动子进程变量可能和你在 shell 里看到的不一样。这提醒我们环境变量并不是越用越好它本质上是一种全局隐含配置使用过多反而会让程序变得难以预测。设计新程序时重要配置优先通过配置文件或命令行参数显式传入而不是依赖环境变量层层传递。7. 实操心得收尾再聊几个小细节写了这么多最后说几个我在实操中积累的琐碎心得每个都能帮你少走弯路。关于进程切换不要被“上下文切换开销小”这种说法迷惑。单次切换确实只有微秒级别甚至更低但高频率累积之后耗时占比可能非常大。我遇到过一个高并发网关压测时 P99 延迟不达标排查到最后发现一台机器上堆了太多进程CPU run queue 堆积每毫秒都在切换。解决方案不是说换更快的 CPU而是缩减进程数量、绑核、调整线程模型问题立刻缓解。一把梭“多开进程提升并发”的做法在资源紧张时往往适得其反。关于环境变量建议你记住一个原则进程的环境变量是出生时决定的运行中修改影响有限。凡是需要在子进程里读的参数尽量在 fork/exec 之前设置好并在子进程入口处打日志记录关键变量的值。看到日志里变量缺失先看进程树的继承链再看每一层有没有 unset 或覆盖最后检查是不是 exec 时传错了 envp。按这个顺序查一般十分钟内就能定位。最后再分享一个小技巧调试环境变量问题时用/proc/pid/environ可以直接查看任意进程的环境变量表需要权限。比如有个进程你怀疑环境变量不对可以用tr \0 \n /proc/1234/environ把里面的每一条拉出来看不用打断进程。这个命令在排查后台服务时救过我很多次比反复改代码重新部署高效得多。进程切换和环境变量一个是操作系统底层的调度行为一个是应用层的数据传递机制看起来风马牛不相及但它们串起来就是“一个进程从诞生到运行再到换出”的完整故事。把这条线理清了很多系统问题在你眼里就不再是玄学而是可以一步步定位、验证、解决的工程问题。

相关新闻

Spy++ Lite 3.1.0.1:Windows窗口句柄调试与消息监控实战指南

Spy++ Lite 3.1.0.1:Windows窗口句柄调试与消息监控实战指南

简介:Spy Lite 3.1.0.1 是一款轻量级但功能完备的Windows窗口调试与分析工具,面向C/C、Win32 API开发者及逆向初学者,用于快速获取窗口句柄、解析窗体层级结构、监控控件状态,解决UI元素定位难、消息机制理解浅、跨进程窗口调试无…

2026/10/18 8:51:22 阅读更多 →
主流Shell选型指南:从Bash到Nushell的取舍与迁移

主流Shell选型指南:从Bash到Nushell的取舍与迁移

前两年我给自己手头那套“命令行环境选型清单”起了个代号,就叫WHAT——全称是We Have Alternatives in Terminal。说白了这个清单就回答一个问题:默认shell到底该换哪个。这个问题看着简单,实际踩的人不少。我见过太多“换过去又换回来”的案…

2026/10/18 8:51:22 阅读更多 →
甲流初筛系统与短信计费:医疗信息化中的成本管控实践

甲流初筛系统与短信计费:医疗信息化中的成本管控实践

说实话,这个项目名字一开始看起来有点“混搭”——短信计费是典型的通信业务问题,甲流病人初筛是医疗信息化场景,两个领域八竿子打不着。但做基层诊所信息化系统时,这两个需求偏偏撞到了一起:发热诊室的医生需要登记甲…

2026/10/18 8:51:22 阅读更多 →

最新新闻

MT7663 USB WiFi驱动移植指南:交叉编译、固件加载与wlan0注册

MT7663 USB WiFi驱动移植指南:交叉编译、固件加载与wlan0注册

简介:这份资源是MT7663 USB转WiFi驱动源码包,面向需要在嵌入式Linux平台上移植无线网卡的开发者,尤其适合海思3531等ARM64平台。源码已在海思3531上交叉编译通过,生成的wlan_mt7663_usb.ko约3MB,配套的Makefile.aarch已…

2026/10/18 14:18:27 阅读更多 →
ADC数据手册深度解析:从PDF参数提取到硬件时序实现

ADC数据手册深度解析:从PDF参数提取到硬件时序实现

简介:本资源为MSM381A3729Z9BM1C模拟输出MEMS麦克风的官方英文数据手册(PDF),面向电子工程师、硬件开发人员及声学器件选型技术人员,用于指导该高性能微型麦克风在移动终端与可穿戴设备中的电路设计、PCB布局、SMT贴装…

2026/10/18 14:18:27 阅读更多 →
P1268 树的重量 【洛谷算法习题】

P1268 树的重量 【洛谷算法习题】

P1268 树的重量 网页链接 P1268 树的重量 题目描述 树可以用来表示物种之间的进化关系。一棵“进化树”是一个带边权的树,其叶节点表示一个物种,两个叶节点之间的距离表示两个物种的差异。现在,一个重要的问题是,根据物种之间…

2026/10/18 14:18:27 阅读更多 →
GRBL固件深度解析:从Arduino到工业级CNC运动控制

GRBL固件深度解析:从Arduino到工业级CNC运动控制

简介:本资源是面向嵌入式开发者、DIY数控爱好者及高校机电类专业学生的GRBL开源固件完整源码包,专为基于Arduino的CNC控制器开发与学习设计,解决小型数控设备(如雕刻机、激光切割机)的G代码解析与运动控制核心问题。压…

2026/10/18 14:18:27 阅读更多 →
PAD竞速答题怎么按队伍分组上屏:一场厂区开幕式安全知识答题的系统配置复盘

PAD竞速答题怎么按队伍分组上屏:一场厂区开幕式安全知识答题的系统配置复盘

本文范围:开幕式里的答题环节;PAD型号、组网方式和系统代码不在讨论内。1. 项目背景塔河炼化(中国石化塔河炼化有限责任公司)2026年5月26日在新疆阿克苏地区举行第二届“最强操作”竞赛开幕式,开幕式里安排了一段安全知…

2026/10/18 14:18:27 阅读更多 →
超立方体Ramsey(openai/math 家族171)攻坚日志 H11:row-link商图构造长链路形式化进展(节选)

超立方体Ramsey(openai/math 家族171)攻坚日志 H11:row-link商图构造长链路形式化进展(节选)

超立方体Ramsey(openai/math 家族171)攻坚日志 H11:row-link商图构造长链路形式化进展(节选)专栏:组合概率与形式化审计|标签:Lea(n^4)、极值组合、Ramsey理论、条件局部引理、超立方…

2026/10/18 14:17:26 阅读更多 →

日新闻

基于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/18 12:16:16 阅读更多 →