Linux信号处理实战:sigaction配置、自管道唤醒与EINTR排查
信号机制聊到这里终章终于要面对那个让无数人头疼的问题了收到信号之后到底该怎么办。前面几篇我们说了信号怎么产生、怎么注册、怎么被子进程继承、怎么被阻塞但如果你没把“信号处理”这段吃透前面所有铺垫都白搭。在Linux下写服务端程序SIGTERM优雅退出、SIGHUP重载配置、SIGCHLD回收子进程这些都是绕不开的场景处理不好就是线上事故进程卡死、状态错乱、甚至静默丢数据。这篇我直接把我踩过的坑和最终沉淀下来的一套处理框架写出来分四块讲处理函数的设计约束、sigaction的正确配置、一套可落地的信号处理范式以及常见问题的排查方法。1. 信号处理到底在解决什么问题1.1 一个经常被忽略的前提信号不是“调用函数”那么简单很多人理解信号处理就是给某个信号绑一个函数信号一到函数被调用事情就完成了。但实际上信号处理是异步的。这意味着什么你的主程序可能正在执行任意一条指令可能在malloc可能在printf可能在持锁访问共享数据信号处理器就硬生生插进来了。它不是一个普通的函数调用而是一个从内核态强行插入的用户态执行流。这个“强行插入”带来的后果是你没法预知主程序停在哪个状态。用生活里的场景类比一下就是你正蹲在原地拼一个精密模型突然有人从你背后递一张纸条让你立刻回话。你不能放下手里的活直接去干别的事因为手里还捏着容易碎的原件但信号处理这种事就是强行让你停下手你只能做到“尽量不把模型弄散”。这决定了信号处理函数和普通函数有本质区别它不能随便调用库函数不能随便碰全局结构体不能依赖任何会加锁、会分配内存、会修改内部状态的机制。我在实际项目里见过最典型的翻车现场就是有人在SIGINT处理函数里调用了printf来打印日志。看起来天经地义对吧但printf内部有锁、有缓冲区如果主程序正好执行到printf中间信号一来同一个printf被重入轻则输出错乱重则死锁。更隐蔽的是malloc/free这类函数它们内部有链表结构和锁处理函数里一调用主程序的堆状态可能正好处于半更新状态直接踩烂。1.2 信号处理的两种姿态响应式 vs 集成式面对同一个SIGTERM不同场景的应对逻辑并不一样。一种是最简单的“响应式”姿态收到信号立刻做一点原子性动作比如设置一个全局标志位然后返回主循环检测到标志位后自行收尾退出。另一种是“集成式”姿态把信号当作一种事件源和epoll一起整合进主事件循环由循环统一调度处理。比如用signalfd把信号变成文件描述符读出来再当成普通消息处理。这两种姿态没有绝对优劣但分工明确。响应式适合处理动作极其简单的信号比如SIGCHLD“知道有孩子退出就行具体回收等主循环来做”集成式适合那些需要做复杂动作的信号比如SIGTERM要回写状态、关闭连接、清理临时文件这些逻辑放在信号处理函数里是不可能的只能把它转成事件交给主流程。我后来沉淀的框架核心就是把“响应”和“逻辑”彻底拆开信号处理函数里只做“记录”绝不做“业务”。这种设计不是保守而是保命。2. 处理函数不能乱写这里有一堆潜规则2.1 什么是异步信号安全函数为什么printf是个坑信号处理函数里能安全调用的函数集合POSIX有明确清单叫async-signal-safe函数。你不需要全背但要建立意识库函数不等于可安全调用。puts、printf、fprintf、malloc、free、open这个反而是安全的、read/write文件描述符读写安全、sprintf安全但不建议依赖它做复杂格式化、sigaction、sigprocmask、waitpid、_exit这些在清单上而printf、fopen、fork带锁的、pthread相关的几乎所有函数、locale相关函数都不在。有个很容易踩的坑是因为你直接在命令行写信号处理demo时printf表现正常就以为没事。那是因为概率低主程序刚好不在printf内部冲突未发生。但线上程序数据量大、调用频繁概率再低也扛不住连续跑几个月。不要赌概率信号处理函数里默认不用非安全函数。如果确实想在信号到来时留下点痕迹怎么办两个办法一是用write直接往一个预先打开的文件描述符写几个字节write本身是安全函数二是把信息记到volatile sig_atomic_t变量里在主循环中写日志。2.2 可重入性与volatile sig_atomic_t信号处理函数的另一个核心约束是“可重入性”。可重入的意思是这个函数即使被中断然后再次进入也不会破坏之前的状态。如果一个函数内部只使用局部变量那天然可重入凡是使用全局状态、静态缓冲区、锁的都不可重入。在C语言里这引出一个所有人都会碰到的细节全局标志位到底应该怎么声明答案不是普通int而是volatile sig_atomic_t。这两者的区别很关键。sig_atomic_t保证对该变量的访问是原子操作不会被CPU的加载/存储指令拆成两步volatile则禁止编译器把这个变量的访问优化到寄存器里。如果你声明成普通int编译器在优化模式下可能把它缓存到寄存器主循环读到的还是旧值信号处理函数改了也白改程序就出现“收到信号但毫无反应”的诡异现象。所以经验就是凡是跨信号处理函数和主流程之间传递状态量一律用volatile sig_atomic_t不搞特殊。2.3 别在handler里碰锁哪怕你认为“不太可能冲突”这条我单独拎出来说因为它是重灾区。在信号处理函数里加锁从原理上讲问题不大——前提是主程序当时没持锁。但问题是信号处理函数根本不知道主程序正在干什么。如果主线程持着锁A信号到达处理函数试图取锁A而信号处理函数和主线程在同一个线程里线程就“自己等自己释放锁”直接死锁。这个现象有个经典名字信号处理函数中的死锁陷阱。不只是pthread_mutex_lock任何带锁的函数都不能碰包括很多看似无辜的标准库函数。很多人会天真地想我加个trylock不就行了但trylock的结果不可预测锁状态依赖主程序的进度你没法保证它处于什么状态。结论很简单处理函数里别碰任何锁。如果非要在信号到来时同步资源就把“同步”这件事推迟到主循环里处理函数只管记录事件编号业务逻辑全部放在主循环里加锁处理。3. 从signal到sigaction注册处理的正确姿势3.1 为什么signal()不够用很多初学者用signal()注册处理函数一个回调搞定。但这东西有两个硬伤第一不同Unix系系统上signal()的语义有差异有的系统在信号处理后会把处理方式重置为默认这意味着如果你要持续处理同一个信号每次触发后都要重新注册中间有一个窗口期信号会被默认处置第二signal()不支持屏蔽信号、不支持标志位你在处理一个信号时如果另一个同类信号又来了会直接重新进入处理函数造成重入。所以新代码里不应该再用signal()应该用sigaction()。sigaction支持sa_mask来指定信号处理期间的屏蔽集合支持SA_RESTART让系统自动重试被信号中断的系统调用支持SA_SIGINFO获取信号附带的信息。它是POSIX标准行为语义明确。3.2 sigaction完整参数解析sigaction的原型长这样int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);struct sigaction里有三个关键字段struct sigaction { void (*sa_handler)(int); sigset_t sa_mask; int sa_flags; };sa_handler是处理函数指针。sa_mask是一个信号集表示在处理当前信号期间系统会自动屏蔽这些信号。注意被处理的信号本身在handler执行期间默认被屏蔽除非设置了SA_NODEFER这个默认屏蔽是好事防止重入。sa_flags最常用的是SA_RESTART被信号中断的系统调用read、write、accept等自动重启不返回EINTR。SA_SIGINFO启用sa_sigaction三参数版本可以获得siginfo_t里面有信号来源、发送者PID、信号编号等。SA_NOCLDWAIT仅对SIGCHLD有意义让子进程自动释放不产生僵尸进程但这会丢失waitpid回收的机会慎用。SA_NODEFER处理期间不屏蔽自身信号你基本不会想用它。实际注册时我通常建议用一套统一封装static void set_signal_handler(int sig, void (*handler)(int), int flags) { struct sigaction sa; memset(sa, 0, sizeof(sa)); sa.sa_handler handler; sigemptyset(sa.sa_mask); sa.sa_flags flags; if (sigaction(sig, sa, NULL) -1) { // 这里一般做错误日志不直接exit除非是启动阶段 perror(sigaction); } }注册几个常用信号set_signal_handler(SIGINT, on_signal, 0); set_signal_handler(SIGTERM, on_signal, 0); set_signal_handler(SIGHUP, on_signal, 0); set_signal_handler(SIGCHLD, on_signal, 0);注意SIGCHLD的一个典型坑建议给SIGCHLD加上SA_RESTART否则你主循环里的waitpid或accept可能被它打断。但如果主循环是epoll_wait加不加RESTART都无所谓反正epoll_wait本来就会返回EINTR。3.3 一次性处理与SA_RESTART等flag组合的实际效果不设置SA_RESTART时慢系统调用被信号打断后会返回-1errno置为EINTR。很多新手程序会误判成错误直接break循环退出。设置了SA_RESTART后内核会透明地重新启动这个系统调用代码里不用做任何处理。听起来是不是SA_RESTART永远是好的也不是。如果你在写一个事件循环读超时、select超时、epoll_wait这些场景下你是希望系统调用主动返回EINTR来让循环有机会检查标志位而不是被内核默默重循环饿死。比如你主线程阻塞在accept信号到来设置了全局标志让进程退出如果没有EINTR返回进程会一直卡在accept重启退出不了。所以我的经验是对于纯业务型信号SIGINT/SIGTERM/SIGHUP不要加SA_RESTART让系统调用返回EINTR你的主循环检查到标志立刻退出对于SIGCHLD这种纯粹通知型信号才加SA_RESTART免得它反复干扰业务循环。这算是信号处理里一个容易被忽视的设计决策不是所有信号都该用同一套flag。4. 一套真实可用的信号处理框架4.1 设计思路全局状态 自管道唤醒综合上面的所有约束我最终用的方案很朴素但是经得起线上考验。核心思想是三个词handler里只置位用一个volatile sig_atomic_t数组记录每个信号是否到达。不靠标志位轮询靠唤醒因为如果主线程阻塞在epoll_wait上信号置位了主线程也不知道所以需要一个“唤醒机制”。最经典的是自管道self-pipe trickhandler里往一个管道写一个字节主循环的epoll里监听这个管道的读端有数据就醒。主循环统一处理醒来后主循环读管道清理标志位执行真正的业务逻辑退出、重载配置、回收子进程。自管道这个技巧是靠谱的不过现在Linux出了signalfd可以更优雅——直接从fd读信号。但这个手自管道的方式在可移植性和对已有事件循环侵入性方面有不可替代的优势值得先讲透。4.2 完整代码与逐步解释#include stdio.h #include unistd.h #include signal.h #include errno.h #include string.h #include sys/epoll.h #include sys/socket.h #define MAX_SIGNAL_EVENTS 16 static int pipe_fds[2]; static volatile sig_atomic_t g_signal_flag[NSIG]; static void signal_handler(int sig) { // 只做两件事置位 写管道唤醒主循环 g_signal_flag[sig] 1; int saved_errno errno; ssize_t r write(pipe_fds[1], , 1); (void)r; errno saved_errno; } static void setup_signal_handlers(void) { struct sigaction sa; memset(sa, 0, sizeof(sa)); sa.sa_handler signal_handler; sigemptyset(sa.sa_mask); sa.sa_flags 0; // 不设置SA_RESTART让epoll_wait返回EINTR sigaction(SIGINT, sa, NULL); sigaction(SIGTERM, sa, NULL); sigaction(SIGHUP, sa, NULL); // SIGCHLD单独处理可以设置SA_RESTART避免它干扰waitpid struct sigaction sa_chld; memset(sa_chld, 0, sizeof(sa_chld)); sa_chld.sa_handler signal_handler; sigemptyset(sa_chld.sa_mask); sa_chld.sa_flags SA_RESTART; sigaction(SIGCHLD, sa_chld, NULL); } static void push_signal_to_pipe(void) { char buf[64]; ssize_t n read(pipe_fds[0], buf, sizeof(buf)); (void)n; } static void handle_pending_signals(void) { for (int i 1; i NSIG; i) { if (!g_signal_flag[i]) { continue; } g_signal_flag[i] 0; switch (i) { case SIGINT: case SIGTERM: // 业务退出动作写日志、关连接、清理资源 // 这里只做最小演示 exit(0); break; case SIGHUP: // 重载配置 // reload_config(); break; case SIGCHLD: // 回收子进程 while (waitpid(-1, NULL, WNOHANG) 0){ } break; default: break; } } } int main(void) { if (pipe(pipe_fds) -1) { perror(pipe); return 1; } setup_signal_handlers(); int epfd epoll_create1(0); struct epoll_event ev; ev.events EPOLLIN; ev.data.fd pipe_fds[0]; epoll_ctl(epfd, EPOLL_CTL_ADD, pipe_fds[0], ev); printf(server running, pid%d\n, getpid()); struct epoll_event events[64]; while (1) { int n epoll_wait(epfd, events, 64, -1); if (n 0) { if (errno EINTR) { // EINTR说明是信号打断的直接回到循环顶部处理 handle_pending_signals(); continue; } perror(epoll_wait); break; } for (int i 0; i n; i) { if (events[i].data.fd pipe_fds[0]) { push_signal_to_pipe(); handle_pending_signals(); } else { // 其他fd的业务处理比如socket接收 } } } return 0; }这个框架的关键点在于handler里write管道哪怕没有内容只写了1字节也能让epoll_wait立即返回。主循环里分别处理EINTR和管道两种唤醒路径逻辑上等效都走进了handle_pending_signals()。处理函数置位后不清理管道也没关系只要在循环里清掉即可写重复字节不影响语义。这里的exit(0)是演示用的生产环境不要直接在handle_pending_signals里exit应该把“退出”状态设成全局标志让主循环函数一层层return回去最后在main里统一清理退出。第4点是很多人的坑收到SIGTERM后想立刻exit结果没来得及关闭数据库连接数据没落盘。正确做法是让信号只负责把“要退出”这个意图通知到主流程退出前的清理必须主流程点做。4.3 用signalfd改造事件循环如果项目要求更干净的实现Linux专门为这个场景准备了signalfd。它把信号变成一个fd可以直接塞进epoll。这样就没有自管道那一堆手动逻辑了代码更简练。#include sys/signalfd.h sigset_t mask; sigemptyset(mask); sigaddset(mask, SIGINT); sigaddset(mask, SIGTERM); sigaddset(mask, SIGHUP); sigaddset(mask, SIGCHLD); // 关键要先屏蔽这些信号signalfd才能收到 sigprocmask(SIG_BLOCK, mask, NULL); int sfd signalfd(-1, mask, SFD_NONBLOCK); epoll_ctl(epfd, EPOLL_CTL_ADD, sfd, ev);之后主循环里read这个fd会返回一个struct signalfd_siginfo结构体里面有ssi_signo信号编号、ssi_pid发送者PID、ssi_code等信息。信号处理函数就彻底不需要了直接在主循环里做业务。用signalfd有个必须注意的坑必须在调用sigprocmask把它们屏蔽掉否则信号还是走默认处理。而且屏蔽信号要在创建sfd之前做否则信号可能在注册前就来造成进程退出。自管道和signalfd本质上是同一件事——把信号变成事件源。选哪个我的建议是如果代码需要跨平台比如要兼容其他Unix用自管道如果确定跑Linux用signalfd更简洁还不用写handler。5. 常见问题与排查技巧实录5.1 问题一EINTR导致read返回-1程序“莫名其妙”退出这是所有信号初学者的第一道坎。现象是程序跑得好好的一收到信号某个read/write/accept直接返回-1你的代码判断if (ret 0) break程序就优雅退出了——不是信号处理本身退的是EINTR让你误以为出错。解决方法有两种。一是注册时加SA_RESTART二是在read/write的循环里判断errno EINTR如果是就continue重试。注意不要在非慢系统调用如磁盘读写上无脑重试EINTR对普通快设备几乎不会出现。还有一个需要注意的区别epoll_wait、select、poll即使加了SA_RESTART也可能返回EINTR因为它们的语义就是可以被打断的要单独处理。5.2 问题二多个信号混合时处理函数竞态如果SIGTERM和SIGHUP几乎同时到达handler会被连续调用两次。如果handler里写同一个管道没问题但如果handler里直接操作一个结构体哪怕只是做自增也可能因为两次进入导致逻辑错乱。这就是为什么我强调“handler里只置位”这个原则。再多说一句即使有了二级制标志位还是可能出现信号到达顺序和标志位不一致的情况。比如SIGHUP和SIGTERM都到了但你只记录“有信号”忘了区分是哪一个那就没法做对应的业务逻辑。所以记录时要按编号分别标记这才是上面代码里用数组而非单个int的原因。5.3 问题三信号处理函数里调用非安全函数导致的诡异崩溃这种崩溃的表现是最难排查的不是每次触发都崩而是间歇性崩溃有时几天才出现一次core dump的调用栈上主程序在malloc里handler也在malloc里两个malloc互相踩。排查定位到这种问题时通常解决方案有两个一是把所有非安全调用从handler里薅出来只保留安全函数二是干脆换用signalfd彻底屏蔽对handler的需要。很多团队从自管道迁移到signalfd就是为了根治这类问题。如果没法快速改代码可以在编译期加-Werrorframe-larger-than之类的检查辅助定位但治标不治本。核心还是设计层面把handler做的事压缩到最小。5.4 信号排查工具箱与速查表strace -f -e tracesignal ./app可以看所有信号收发和handler执行前后系统调用的现场。cat /proc/ /status里SigBlk、SigIgn、SigCgt三个字段分别表示阻塞、忽略、捕获的信号的位掩码可以用来确认配置是否正确。kill -l 可以列出当前系统所有信号的名字和编号有些系统信号编号有差异查表不要凭记忆。gdb下用handle SIGTERM stop / SIGTERM nostop 可以控制gdb是否在信号发生时停住。常见问题速查现象可能原因排查切入点收到信号进程直接退出handler未注册或信号被默认处置cat/proc/ /status里的SigCgtread/accept返回-1退出EINTR未重试errno是否为EINTR收信号后主循环无反应标志位未加volatile或编译器优化strace看系统调用是否执行收信号后死锁handler里调用了带锁函数检查handler调用栈SIGCHLD信号丢失未设置SA_NOCLDWAIT或未注册handlerwaitpid返回-1 ECHILDhandler执行后业务没执行信号被屏蔽或线程分发错误检查信号掩码继承链我个人在实际操作中的体会是信号处理这件事98%的坑都集中在“你以为信号是同步的而它实际上是异步的”这个混淆上。只要你坚定不移地认为handler是“记录器”而不是“执行器”大半问题都不会发生。最后一招分享给还在用signal()的老项目全局替换成sigaction并不难一次搜索替换加测试就好这个投入绝对值得。多线程程序里处理信号更复杂建议用pthread_sigmask在非主线程统一收信号回头的确可以单独开一篇讲我还没把多线程信号处理完全讲透这里先不展开了。

相关新闻

HFSS与CST天线仿真实战:建模流程、关键设置与避坑指南

HFSS与CST天线仿真实战:建模流程、关键设置与避坑指南

搞射频的同行应该都有过这种经历:模型搭得挺像回事,仿真结果出来S11惨不忍睹,方向图偏得离谱,仔细排查一圈才发现根本不是设计错误,而是网格没剖好、端口设置有误,或者求解收敛判据太松。天线仿真这件事&am…

2026/10/17 3:35:54 阅读更多 →
轻量级Agents SDK实战:快速搭建多Agent协作的AI团队

轻量级Agents SDK实战:快速搭建多Agent协作的AI团队

1. Agents SDK 到底是什么,凭什么能组个“AI 团队”这次我在一个内部沟通模拟场景里试用了当下讨论度很高的 Agents SDK——一个主打轻量级的多 Agent 工作流框架,核心思路是把你手头那些只能“一问一答”的模型调用,包装成一个个可以互相协作…

2026/10/17 3:35:54 阅读更多 →
鸿蒙Flutter大规模列表优化:纯Dart工具list_utilities实战解析

鸿蒙Flutter大规模列表优化:纯Dart工具list_utilities实战解析

最近在做鸿蒙(HarmonyOS NEXT)列表页重构的时候,被一个老问题折磨得够呛:Flutter 生态里那些处理集合数据的工具库,拿到鸿蒙上要么编译不过,要么跑起来性能断崖式下跌。尤其是当数据量到十万级、还要做分组…

2026/10/17 3:34:53 阅读更多 →

最新新闻

预测编码与反向传播:从生物合理性到深度学习的新型训练范式

预测编码与反向传播:从生物合理性到深度学习的新型训练范式

1. 从一场持续多年的争论说起:大脑真的在做反向传播吗这几年深度学习圈子里有一个话题,每隔一阵就会被翻出来吵一轮,那就是反向传播(Backpropagation)在生物大脑中是否真实存在。说实话,这个问题表面上像是…

2026/10/17 5:05:18 阅读更多 →
支付宝沙箱验签失败?5个隐蔽排查点与Hutool避坑指南

支付宝沙箱验签失败?5个隐蔽排查点与Hutool避坑指南

刚处理完一个同学的沙箱联调问题,支付宝返回invalid-signature,他第一反应就是怀疑密钥配错了,翻来覆去重生成密钥对、换公钥,折腾了一下午没解决。后来我远程看了下代码,问题根本不在密钥本身——是他的验签串拼接时多…

2026/10/17 5:05:18 阅读更多 →
Linux安全防护机制详解:从ASLR、NX到Canary绕过与ROP利用

Linux安全防护机制详解:从ASLR、NX到Canary绕过与ROP利用

搞PWN的人,绕不开Linux安全防护机制。每次拿到一个二进制,我第一件事就是丢进checksec看它开了哪些保护——这几乎成了肌肉记忆。因为PWN的本质是让程序执行我们期望的代码,而Linux安全防护机制就是堆在漏洞和利用之间的一堵墙。你不仅要懂漏…

2026/10/17 5:05:18 阅读更多 →
从多层因果世界到自我进化:构建通用模拟系统的架构设计与工程实践

从多层因果世界到自我进化:构建通用模拟系统的架构设计与工程实践

1. 从"模拟器"这个词说起:为什么我想做一个通用模拟系统聊到"模拟器",大多数人脑子里蹦出来的第一反应是安卓模拟器、思科模拟器、PS3模拟器这类具体工具——它们干的事情很明确:在一个环境里复刻另一个环境的行为&#…

2026/10/17 5:05:18 阅读更多 →
H3C IP上一跳保持技术:解决异地出口容灾回程路径难题

H3C IP上一跳保持技术:解决异地出口容灾回程路径难题

1. 异地出口容灾到底在防什么先把场景说清楚。所谓“职场数据中心异地出口容灾”,指的是一个企业有两个数据中心,主数据中心和灾备数据中心,各自有独立的互联网出口链路。正常情况下,所有业务流量从主数据中心的出口出去&#xff…

2026/10/17 5:05:18 阅读更多 →
Unity Shader实现航天器再入灼烧特效:温度映射、边缘发光与烧蚀残留全解析

Unity Shader实现航天器再入灼烧特效:温度映射、边缘发光与烧蚀残留全解析

/* 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 5:04:17 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 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/16 21:54:38 阅读更多 →
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/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练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 阅读更多 →