匿名管道原理与避坑指南:从文件描述符到内核缓冲区
说到匿名管道我脑子里第一时间跳出来的就是那个经典实验在Shell里执行cat file | grep xxx或者程序员面试时被反复问到的pipe fork。它名字里带个管道用起来又是一对文件描述符read()/write()和读写文件几乎没区别但偏偏没有路径、不能open()、不落盘。最早自己学操作系统时我对这一点非常费解既然连文件名都没有凭什么说它是“基于文件系统”的进程通信方式后来认真把用户态的调用链、内核里的struct file与file_operations往下追了一遍再把父子进程通信的Demo写熟才真正建立起完整的图景。这篇文章就围绕这个点展开匿名管道如何借文件描述符的壳、走内核缓冲区的里子以及实际项目中用管道时最容易出事的边界情况。1. 先搞清楚匿名管道为什么“没有路径”却能像文件一样读写1.1 一个反直觉的事实pipe() 一次返回两个文件描述符如果你写过最基础的管道Demo应该记得这个系统调用的签名#include unistd.h int pipe(int pipefd[2]);一次调用内核给你两个文件描述符pipefd[0]是读端pipefd[1]是写端。关键在于这里完全没有文件名、没有路径、没有open()步骤。你平时打开一个普通文件需要先拿到字符串路径再经由文件系统解析出 inode最后才能得到文件描述符。pipe()把这个过程整个跳过了。这就带来一个很自然的困惑一个没有路径、没有目录项、没法通过文件系统去 “找” 的东西怎么还能用read()/write()去操作难道操作系统不该先知道“文件在哪”才能读写吗实际上从用户态进程的视角看文件描述符就是一切的入口。进程打开文件、管道、socket、设备节点最终都会落到一张文件描述符表里。只要管道的两个端点在这个表里存在进程就可以像操作文件一样操作它们。路径只是“打开文件的工具”一旦打开完成后续的read()/write()根本不再关心路径是什么。匿名管道做的就是这一件事绕过了“打开”步骤直接把两个端点塞给进程。1.2 “基于文件系统”的真正含义复用的是文件抽象接口不是磁盘存储如果只是描述层面说“管道像文件”那还没到点子上。内核里真正让“像文件”成立的是虚拟文件系统VFS这一抽象层。每个打开的文件在内核里都对应一个struct file对象这个对象里除了文件偏移、读写标志更重要的是一个指向具体操作函数的指针表也就是file_operations。平时我们读写 ext4、xfs 上的普通文件时read()系统调用走到 VFS 层最终会调用 ext4 文件系统实现的那一坨函数而read()走到管道的文件描述符上时VFS 层会把请求分发给管道专用的pipe_read()、pipe_write()。所以匿名管道“基于文件系统”这句话准确说是“基于文件系统的接口框架”——它挂靠在文件描述符这套语义之下但它根本没有下层的真实文件系统实现。数据不会写到磁盘的某个数据块里而是缓存在内存中的一个环形缓冲区中。VFS 就像一个分发中心入口都是同一套read()/write()接口进去之后各路由各的目的地。这个设计非常巧妙。因为 Linux 上一切皆文件所以很多编译工具、脚本程序天然就懂管道。比如你从 Bash 里把一个普通命令的输出接到另一个命令的输入两个命令之间没有约定任何协议它们只知道自己“在读写一个文件”。1.3 验证“数据不落盘”写入 1GB 数据会撑爆磁盘吗这年头需要用实验验证的事情最好直接动手试。我以前带一个刚转行的同学时跟他说“管道不落盘”他总是将信将疑。于是我让他做了一个小实验先用mkfifo创建一个命名管道然后用dd往里塞 1GB 的随机数据同时在另一个终端用程序慢速读。跑完看一眼磁盘占用。他自己跑完之后发现一件很有意思的事无论往管道里塞了多少数据磁盘上的文件大小始终是 0。因为mkfifo创建的那个“文件”在文件系统里只是一个索引节点标识真正承载数据的是内核缓冲区。匿名管道连这个“壳”都省了内核里只保留文件描述符和缓冲区甚至连目录项都不需要。这个实验可以直接做也可以换成匿名管道验证。一个更轻量的方法是在进程目录下看一眼文件描述符指向的内容ls -l /proc/pid/fd/1这类命令会显示管道符号。注意别拿生产环境开刀本地虚拟机随便试。2. 父子进程间跑通一份完整Demopipe / fork / close 的生命周期细节2.1 可直接编译运行的 Demo 代码看原理看了半天不如动手写一个最小可运行的例子。下面这份代码是我平时讲课时经常用的它展示了最核心的用法父进程向管道写入一段字符串子进程读取这段字符串并统计字节数。/* * pipe_demo.c * 父进程向管道写入文本子进程从管道读取并输出接收内容 * 编译: gcc -o pipe_demo pipe_demo.c * 运行: ./pipe_demo */ #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/wait.h #define BUFFER_SIZE 4096 int main(void) { int pipefd[2]; pid_t pid; const char *msg hello from parent, through anonymous pipe.; if (pipe(pipefd) -1) { perror(pipe); exit(EXIT_FAILURE); } pid fork(); if (pid -1) { perror(fork); exit(EXIT_FAILURE); } if (pid 0) { /* 子进程只从管道读 */ char buf[BUFFER_SIZE]; int total 0; int n; close(pipefd[1]); /* 子进程用不到写端关掉 */ while ((n read(pipefd[0], buf total, BUFFER_SIZE - total - 1)) 0) { total n; } buf[total] \0; printf([child] received %d bytes: %s\n, total, buf); close(pipefd[0]); exit(EXIT_SUCCESS); } else { /* 父进程只向管道写 */ close(pipefd[0]); /* 父进程用不到读端关掉 */ fprintf(stderr, [parent] sending %zd bytes...\n, strlen(msg)); write(pipefd[1], msg, strlen(msg)); close(pipefd[1]); /* 写完后关闭写端子进程才能收到 EOF */ waitpid(pid, NULL, 0); fprintf(stderr, [parent] child done.\n); } return 0; }代码逻辑不复杂先pipe()拿到两个描述符再fork()出子进程。fork()完成后父子进程各自拥有这份文件描述符表的副本。接下来就可以各司其职了。2.2 关上不用的那个端点EOF 语义的根基很多新手会把上面代码里的close()当作“可写可不写”的清理动作其实大错特错。关闭不需要的管道端点是管道通信能够正确结束的关键。read()从管道读数据时什么情况下会返回 0也就是我们常说的“读到文件末尾”答案是当且仅当管道上所有写端文件描述符都被关闭时。请注意“所有”这个词。fork()之后管道写端其实有两个引用父进程的pipefd[1]和子进程继承的pipefd[1]。如果子进程不关闭写端即使父进程写完后关了pipefd[1]管道里仍然存在一个活着的写端引用子进程的read()会一直阻塞等待新数据永远等不到 EOF。这在程序里表现出来就是进程挂死。所以 Demo 里我专门在子进程读数据前close(pipefd[1])这个动作的本质是告诉内核“我这个进程不会再往这个管道里写数据了”从而让读端可以正确感知到数据流结束。反过来父进程也必须关闭读端。父进程只负责写如果不关读端它自己手里还攥着一个读端引用这本身不会立刻引发故障但对后续扩展非常危险——一旦父子进程角色互换或出现信号处理逻辑多出来的引用会干扰 EOF 判断。编程规范上管道两端谁不需要谁立刻关这是最容易养成的好习惯。2.3 运行与追查用 strace 看系统调用序列代码保存成pipe_demo.c后编译运行gcc -o pipe_demo pipe_demo.c ./pipe_demo预期输出类似[parent] sending 43 bytes... [child] received 43 bytes: hello from parent, through anonymous pipe. [parent] child done.如果你跟我一样喜欢钻系统调用细节可以顺手用strace看一眼整个过程strace -f -e tracepipe,fork,read,write,waitpid ./pipe_demo-f选项会同时跟踪子进程。输出里你能看到pipe()返回两个 fd然后fork()再接着父子进程各自执行read()和write()。这个东西的价值在于它把“文件描述符被继承”这件事直接砸到你眼前子进程里操作的是同一对 fd 编号但它们已经是两份独立的引用。理解了这一层后面很多管道相关的诡异问题就都说得通了。3. 把管道放进进程通信选型地图文件式通信的边界与取舍3.1 几种“文件式”通信方式的横向对比实践里只要涉及两个进程交换数据就一定会遇到选型问题。有一个非常常见的误区是把匿名管道和基于“真实文件”的通信混为一谈。我整理了一张表可以直观对比通信方式是否有路径数据是否落盘通信双方是否需要亲缘关系典型接口数据容量边界匿名管道pipe无否必须通常父子进程read/write内核缓冲区默认约 64KB命名管道FIFO有仅节点不落数据否open/read/write内核缓冲区普通文件通信有是否open/read/write/lseek受磁盘容量约束内存映射共享内存shm/mmap通常有否否mmap/读写内存物理内存Unix Domain Socket有sock 路径否否socket/bind/send/recv内核 socket 缓冲区这张表最大的价值是可以帮你立刻看出匿名管道的位置它是“文件接口”和“内核内存传输”的结合体。普通文件通信数据落在磁盘上天然要面对写入延迟、断电一致性、残留文件清理等问题匿名管道完全回避这些但它也因此限定通信只在“管道创建后 fork 出来的继承关系”内有效。3.2 选型时的三个判断维度我给自己总结了一套选型判断法遇到进程间通信需求时问三个问题第一个问题通信双方是不是同一个父进程 fork 出来的兄弟进程或父子进程如果是且需求只是单向传递字节流匿名管道几乎是最省事的方案——不需要任何额外依赖不用考虑文件路径冲突性能也不错。如果双方没有亲缘关系那就不能选匿名管道。第二个问题数据量大概有多大如果你预计单次传输量超过几十 MB管道那点内核缓冲区根本兜不住虽然阻塞式读写本身不会丢数据但反复唤醒、拷贝会造成严重的性能开销。数据量大时优先考虑共享内存靠自己的业务协议去同步边界。第三个问题通信双方的生命周期是否重叠管道是壳跟着进程走的临时设施进程一退出管道就销毁。如果一方可能先退出、另一方还要继续运行就需要命名管道或者持久化的消息队列否则会出现生产者和消费者的生命周期错配。这些判断维度不是我凭空设计的而是从真实项目里一点点磨出来的。早期写某个模拟跨平台系统时我为图省事在不需要亲缘关系的组件之间强套了命名管道结果每次重启组件都要先清理残留的 FIFO 节点后来换成了 socket 方案整个世界清净多了。3.3 管道和共享内存极端情况下的哲学差异有人可能会问既然管道这么方便为什么大流量场景都去用共享内存这就涉及两者的根本哲学差异。管道的本质是“流”它天然适合生产者和消费者速率不一致的场景。生产者写不过来缓冲区满了就阻塞消费者处理不过来数据就排队等在内核里。这种背压机制是管道自带的不需要业务层做任何事。共享内存的本质是“块”它不负责流量控制只有一块内存区域双方各自往里写往里读谁快谁慢由程序自己协调。处理不好就是一堆锁、标志位、内存屏障。但好处同样明显零拷贝读取、极低延迟可以支撑超高吞吐。所以极端情况下选择从来不是“哪个更好”而是“你的问题更接近流模型还是块模型”。如果你是在写一个实时日志采集管道希望下游慢吞吞处理时上游也能正常推进管道是自然的选择如果你是在做高频行情数据分发每一笔数据都想尽可能快地给到多个消费者那共享内存才是正解。顺着这个思路你还会发现另一个有意思的中间态Linux 的memfd_create可以创建一块“看不见路径的文件”它可以被映射进多个进程也可以像文件一样读写却完全驻留内存。这就是另一次“文件系统接口与真实存储解耦”的实例不过那就是另一个话题了。4. 真实项目里最容易被管道咬到的四个坑及排查链路4.1 坑一少关闭一个 fd父子进程直接互相“死等”我印象最深的一次踩坑发生在某个模拟日志转发系统上。一个父进程负责从网络接口收数据然后扔给子进程做统计。代码逻辑初看起来没问题父进程write()完就关闭了写端子进程循环read()按道理会在管道 EOF 后退出。但实际跑起来子进程一直不退出。我一开始以为是统计逻辑太慢后来发现它是卡在read()上。当时排查思路是这样的先用strace -p 子进程pid挂上去发现子进程阻塞在read(6, ...)上也就是说它没有等到 EOF。那肯定还有一个写端没关。再检查父进程的/proc/父进程pid/fd发现父进程的pipefd[1]竟然还在。原因说来也简单父进程在fork()之前创建了另一个业务线程这个线程通过函数参数拿到了管道写端的一份副本。我们只关闭了主流程里的写端线程持有的副本一直没关。内核判断“所有写端是否关闭”时只看文件描述符引用的总数不会管你是哪个进程哪个线程。只要还有一份引用活着read()就会一直认为后面还可能有数据。修复方法也很直接把所有传递过写端 fd 的地方全部梳理一遍确保不再使用后立即关闭。为了防止这种问题复发我后来在项目里立了一条规矩管道 fd 不得跨线程传递如果必须传递就由创建管道的线程负责统一关闭。这条规矩从那以后再没让我栽过跟头。4.2 坑二读端被意外关闭写进程收到 SIGPIPE 退出有次在调试一个数据采集脚本时发现采集进程总是无征兆消失退出状态码为 141。这个数字很多 Linux 老手看一眼就明白了但我当时还是花了一点时间才反应过来——141 等于 128 加信号编号 13也就是进程被SIGPIPE信号杀掉了。SIGPIPE 的触发条件是向一个“已经没有读端”的管道写入数据。换句话说管道的读端全部关闭你却还在往里面写。内核出于防止无意义写入的考虑直接向写进程发送 SIGPIPE默认动作是终止进程。这个坑最阴险的地方在于它常常不是第一现场。比如某个进程 fork 了一个子进程子进程把读端关了但父进程还在往管道里写而且由于写的时机不确定可能第一次写没问题第二次、第三次就突然被杀。数据量小的时候完全不影响数据量一上来就崩溃。碰到这种情况我建议先明确业务上“读端缺失”是不是可接受场景。如果读端确实可能先于写端退出而你又希望写进程继续存活就要在初始化阶段对管道写端做处理signal(SIGPIPE, SIG_IGN)然后检查write()的返回值一旦返回EPIPE错误就清理资源退出。不过这里我要多说一句忽略 SIGPIPE 是有代价的因为你必须在每次 write 失败时都做好错误处理否则容易出现“数据没发出去但程序毫无感知”的隐患。4.3 坑三管道缓冲区写满时的阻塞和“背压”很多人默认管道是随便写的忽略了内核缓冲区容量这个概念。Linux 上匿名管道的缓冲区默认容量通常是 64KB 左右具体可以通过fcntl(fd, F_GETPIPE_SZ)查询不同内核版本会略有差异。当缓冲区满了之后write()会阻塞直到读端消费掉一部分数据腾出空间。这个机制本身是保护性的它的意义是防止一个进程无限制地产生数据把内存打爆。但如果你没意识到这个机制就会在程序里碰到“明明我往管道里写了几百 MB数据也没丢可程序就是比预期慢很多”的困惑。我在一个批处理任务里就犯过这个错。当时以为 write 只是把数据复制到内核速度应该很快结果发现写入几 GB 数据时耗时不可接受。用perf record一查大量的时间停在管道写等待上。问题是下游进程在分批读每批之间还有业务计算上游却希望一股脑把所有数据都倒进去。意识到这是背压机制之后方案就清晰了。一种做法是适当增大管道缓冲区fcntl(fd, F_SETPIPE_SZ, size)可以缓解写阻塞频率。但这只是延后问题不是解决本质。更靠谱的做法是调整整体处理节奏让上下游的吞吐能力匹配或者干脆换用带持久化能力的通信方式让上游不会被慢速下游拖死。4.4 坑四以为管道适合传大对象导致隐藏的性能悬崖最后一个坑比较隐蔽。管道本身不会丢数据这一点很多人都知道。于是有人就会想既然不丢数据我用管道传一张几十 MB 的图片应该也没问题吧最多慢一点。这个想法起初没有错但它忽略了管道传输一个致命的问题数据在内核缓冲区和用户进程缓冲区之间反复拷贝。每写一次数据从用户态拷贝到内核态环形缓冲区每读一次又拷回用户态。几十 MB 的数据传来传去内存拷贝开销和上下文切换开销会迅速累积。更糟糕的情况是当多个进程或线程同时操作同一管道时每个读端和写端的竞争会引入大量系统调用、唤醒和调度延迟。我见过有人拿管道当消息总线在两个服务之间传输结构化的 JSON 报文单个报文很小但频率极高结果大量 CPU 时间都耗在系统调用上业务逻辑反而被拖慢了。针对这个坑我的建议是量体裁衣。管道适合传流式数据、小报文、命令序列不适合传大文件、高频高吞吐的结构化数据。后者要么走共享内存要么走 socket直接把数据留在内核协议栈的缓冲区甚至配合sendfile()实现零拷贝。这不是说管道垃圾而是说它有自己的合理使用半径超出半径再用它就是你自己的问题了。我自己现在写代码时已经形成了一套惯性判断先看通信双方有没有亲缘关系再看是否流式单向再看数据量级三个条件都满足才用管道。即便这样也还是会时不时撞上某些边界情况比如标志位没设置导致阻塞模式不对、多线程环境里 fd 泄漏问题。每踩一次对管道“基于文件系统却又不是真文件”的理解就更深一层。希望这篇梳理也能帮你少走一段弯路。

相关新闻

2026 AI编程工具终极对决:Claude Code、Cursor与Copilot如何选

2026 AI编程工具终极对决:Claude Code、Cursor与Copilot如何选

最近这一年,只要身边有人在写代码,就绕不开三个名字:Claude Code、Cursor,还有已经火了很多年的Copilot。打开技术社区,铺天盖地都是“谁取代谁”的争论,有人吹终端自动化,有人夸编辑器内联补全…

2026/10/11 12:49:37 阅读更多 →
深度学习目标检测实战:基于YOLO的红枣识别全流程解析

深度学习目标检测实战:基于YOLO的红枣识别全流程解析

简介:一套基于Python深度学习的红枣识别算法毕业设计资料,面向计算机、人工智能相关专业学生与开发者,可作为课程设计、论文答辩或项目实践的参考。内容涵盖红枣特征分析、识别流程设计、模型搭建、训练优化与性能评估,帮助读者形…

2026/10/11 12:49:37 阅读更多 →
PCB缺陷检测数据集处理:VOC转YOLO格式与YOLOv8训练实战

PCB缺陷检测数据集处理:VOC转YOLO格式与YOLOv8训练实战

简介:面向电子制造质检与深度学习开发者的印刷电路板缺陷检测数据集,已按PASCAL VOC标准完成标注。压缩包内共有八百九十三个文件,包含四百四十五张缺陷图片及一一对应的XML标注文件,其中记录各缺陷的边界框与类别信息&#xff1b…

2026/10/11 12:49:37 阅读更多 →

最新新闻

Java 实现超大附件上传:分片、断点续传与合并校验实战

Java 实现超大附件上传:分片、断点续传与合并校验实战

很多做文件上传功能的同学,第一次接到“超大附件”需求时都以为只是加个参数、调大内存就能搞定。结果一跑真实文件,几百 MB 可能还能撑住,到了几个 GB 甚至十几个 GB,要么请求超时,要么服务端内存直接打满&#xff0c…

2026/10/11 13:35:01 阅读更多 →
私有化交付自动化巡检引擎:编写覆盖 50 项软硬件指标的零依赖前置验收脚本

私有化交付自动化巡检引擎:编写覆盖 50 项软硬件指标的零依赖前置验收脚本

在私有化项目交付的“翻车排行榜”上,排在第一名的永远不是“业务系统有 Bug”,而是“客户提供的底层服务器环境存在极其隐蔽的致命硬伤”:实施工程师辛辛苦苦在客户内网机房忙活了整整一天,终于把全部容器和微服务拉齐&#xff0…

2026/10/11 13:35:01 阅读更多 →
微服务核心降级矩阵实战:当上游依赖与第三方支付瘫痪时如何保住核心交易

微服务核心降级矩阵实战:当上游依赖与第三方支付瘫痪时如何保住核心交易

在大促高并发或突发网络割接等极端场景下,分布式微服务系统最危险的状态不是“所有机器全死”,而是“某一个非核心的下游依赖半死不活”:比如商品详情页调用的“个性化推荐服务”突然发生 GC 停顿,响应耗时从 10ms 拉长到 3 秒&am…

2026/10/11 13:35:01 阅读更多 →
红外电力设备目标检测数据集实战:从VOC转YOLO到切图推理全流程

红外电力设备目标检测数据集实战:从VOC转YOLO到切图推理全流程

简介:这份红外电力设备目标检测数据集面向电力AI检测、智能电网运维及计算机视觉方向的研究者与开发者,提供可直接用于YOLO系列模型训练的真实热成像标注数据。资源包共2000个文件,以1474个txt标注文件、524张jpg热成像图片为主,另…

2026/10/11 13:35:01 阅读更多 →
Java超大文件分片上传实战:解决OOM与连接超时

Java超大文件分片上传实战:解决OOM与连接超时

在 Java 后端开发里,“JAVA http 请求”本身不算难事,难点是当请求体变成几个 GB 的超大附件时,问题会全部冒出来。我之前负责一个数据文件交换平台,用户经常上传 3GB、6GB 的现场采集包,最初同事按普通 Multipart 方式…

2026/10/11 13:35:01 阅读更多 →
SS728M05身份证验证终端Windows接口包对接指南:从DLL调用到稳定部署

SS728M05身份证验证终端Windows接口包对接指南:从DLL调用到稳定部署

简介:面向Windows平台的神思SS728M05身份证验证SDK开发包,专供需要集成二代身份证读取、解码与真伪校验的开发者使用。接口封装了神思硬件设备的底层通信协议,适用于银行开户、网络实名认证、酒店登记等实名制场景,开发者无需深入…

2026/10/11 13:34:01 阅读更多 →

日新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/11 0:00:27 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/11 10:45:37 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →