Linux task_struct信号处理与sigpending组织
Linux task_struct信号处理与sigpending组织struct task_struct中信号相关字段分布在多个cache line上直接决定信号投递路径的缓存行为。task_struct-pending是进程级挂起信号集合类型为struct sigpending内部包含一个sigset_t signal64位系统上为两个unsigned long和一个struct list_head list链式队列。thread group共享的signal_struct-shared_pending则存放需要广播到整个线程组的挂起信号。cstruct sigpending {struct list_head list;sigset_t signal;};struct task_struct {/* ... */struct sigpending pending; /* 进程私有挂起信号 *//* ... */struct signal_struct *signal; /* 指向共享的thread group信号描述符 *//* ... */unsigned int siginfo_try_wait:1;unsigned int siginfo_try_wait_seen:1;/* ... */};信号投递入口为__send_signal_locked()。该函数首先判断目标tgid是否等于当前pid——即进程自身发信号——若是则直接写入current-pending否则调用__sigqueue_alloc()分配一个struct sigqueue节点插入目标task-pending.list同时设置pending.signal中对应的bit。这里存在一个关键竞态如果目标进程正在执行do_exit()释放signal_struct__sigqueue_alloc()可能看到的是已置SIGNAL_GROUP_EXIT标志的signal_struct此时必须放弃投递。cstatic int __send_signal_locked(int sig, struct kernel_siginfo *info,struct task_struct *t, bool group, bool force){struct sigpending *pending;struct sigqueue *q;int override_rlimit;int ret 0;pending group ? t-signal-shared_pending : t-pending;if (unlikely(!t-signal)) /* 目标进程正在exit */return -ESRCH;/** 快速路径实时信号或非实时信号忽略rlimit检查* 对于sigqueue溢出场景重试一次后丢信号*/override_rlimit (sig SIGRTMIN) || sig SIGKILL || sig SIGSYS;if (!override_rlimit !sigismember(t-signal-rlim[RLIMIT_SIGPENDING].rlim_cur)) {if (t-signal-nr_queued t-signal-rlim[RLIMIT_SIGPENDING].rlim_cur) {ret -EAGAIN;goto out;}}q __sigqueue_alloc(sig, t, GFP_ATOMIC, override_rlimit, 0);if (q) {list_add_tail(q-list, pending-list);sigaddset(pending-signal, sig);} else if (!is_si_special(info)) {/* 分配失败且不是特殊info丢弃信号 */ret -ENOMEM;goto out;}/* 非实时信号相同sig只保留一个sigqueue丢弃后续重复 */if (sig SIGRTMIN) {struct sigqueue *first list_first_entry_or_null(pending-list, typeof(*first), list);while (first first-info.si_signo sig first ! q) {list_del(first-list);__sigqueue_free(first);first list_first_entry_or_null(pending-list, typeof(*first), list);}}complete_signal(sig, t, group);out:return ret;}信号递送路径complete_signal()的关键决策是选择投递目标线程。对于SIGKILL或SIGSTOP这类终止类信号直接标记整个thread group后唤醒所有TASK_INTERRUPTIBLE状态的成员对于其他信号优先选择当前正在运行的线程通过sigismember(t-signal-curr_target-pending.signal若不可用则遍历thread group找第一个不阻塞该信号的线程。选中的线程通过signal_wake_up()置TIF_SIGPENDING标志然后视当前cpu是否为目标cpu决定是否需要reschedule IPI。cstatic void complete_signal(int sig, struct task_struct *p, enum pid_type type){struct signal_struct *signal p-signal;struct task_struct *t;if (unlikely(sig SIGKILL || sig SIGSTOP)) {/* 终止类信号直接广播 */__for_each_thread(signal, t)signal_wake_up(t, sig SIGKILL);return;}/* 找不阻塞该信号的目标线程 */t signal-curr_target;while (!sigismember(t-blocked, sig)) {t next_thread(t);if (t signal-curr_target)break; /* 所有线程都阻塞 */}if (t-flags PF_EXITING)t p; /* 目标在exit退回发信号者 */signal_wake_up(t, 0);}另一个关键路径是从user mode返回内核时调用do_signal()。entry_SYSCALL_64后检查thread_info-flags的_TIF_SIGPENDING位若置位则跳转至do_notify_resume()再进入do_signal()。这里使用get_signal()从pending链表中逐一取出struct ksignal判断sa_handler是否为SIG_IGN或SIG_DFL对于SIG_IGN直接丢弃信号不计入signal_struct-nr_queues对于SIG_DFL则执行默认动作如do_group_exit()。标准信号1-31在pending.signal中只保留一个bit但list上仍可能有多个sigqueue节点——list遍历时必须通过info.si_signo匹配真实的信号编号。cvoid get_signal(struct ksignal *ksig){struct task_struct *tsk current;struct signal_struct *signal tsk-signal;int sig;for (;;) {sig dequeue_signal(tsk, tsk-blocked, ksig-info);if (!sig)break; /* 所有信号处理完毕 */if (sigismember(tsk-real_blocked, sig))continue; /* 被real_blocked二次屏蔽 */ksig-sig sig;/* ka缓存了handler和flags */if (ksig-ka-sa.sa_handler SIG_IGN) {continue; /* 直接吞掉 */}if (ksig-ka-sa.sa_handler SIG_DFL) {switch (sig) {case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:continue; /* 默认忽略 */case SIGTSTP: case SIGTTIN: case SIGTTOU:do_signal_stop(sig);goto relock;case SIGSTOP:do_signal_stop(sig);goto relock;case SIGKILL:do_group_exit(SIGKILL);default:break;}}return; /* 返回用户信号处理函数 */}/* 所有信号已耗尽清理TIF_SIGPENDING */clear_tsk_thread_flag(tsk, TIF_SIGPENDING);}dequeue_signal()的实现需要同时扫描task-pending和signal-shared_pending两个队列并且必须保持一致性——先取shared_pending再取私有pending中间不能存在抢锁窗口。内部的collect_signal()负责从list头摘取匹配sig的sigqueue节点如果list为空则清除对应的pending.signal bit。实时信号SIGRTMIN保证sigqueue的数量不压缩32个实时信号每个都可以独立排队非实时信号在投递时就做了重复合并所以dequeue时一个信号至多对应一个sigqueue。结构布局上的一个陷阱struct task_struct的pending字段和blocked字段分散在不同的cache line上signal_wake_up()写task-pending时不会invalid目标cpu上blocked字段的cache line。但get_signal()读blocked时若与complete_signal()并发由于二者均持有siglock写者通过siglock的release语义保证了读者能看到完整的pending.signal集合。然而在siglock未持有的检查路径如signal_pending()中只读取TIF_SIGPENDING位而不访问sigpending本体这是安全的——因为TIF_SIGPENDING的set/clear永远在siglock保护下进行。

相关新闻

Linux tc filter_classify分类器链匹配与action执行

Linux tc filter_classify分类器链匹配与action执行

Linux tc filter_classify分类器链匹配与action执行TC(Traffic Control)分类器链的核心入口是filter_classify函数,它遍历挂在qdisc或clas上的filter链,逐一调用每个filter的classify回调进行匹配判决。filter_classify定义在net/…

2026/7/21 10:54:01阅读更多 →
5个实用技巧:轻松掌握iCloud照片批量下载神器

5个实用技巧:轻松掌握iCloud照片批量下载神器

5个实用技巧:轻松掌握iCloud照片批量下载神器 【免费下载链接】icloud_photos_downloader A command-line tool to download photos from iCloud 项目地址: https://gitcode.com/GitHub_Trending/ic/icloud_photos_downloader 你是否曾经担心iCloud中的珍贵照…

2026/7/21 10:54:01阅读更多 →
3分钟上手BOTW存档编辑器:塞尔达传说旷野之息存档修改完全指南

3分钟上手BOTW存档编辑器:塞尔达传说旷野之息存档修改完全指南

3分钟上手BOTW存档编辑器:塞尔达传说旷野之息存档修改完全指南 【免费下载链接】BOTW-Save-Editor-GUI A Work in Progress Save Editor for BOTW 项目地址: https://gitcode.com/gh_mirrors/bo/BOTW-Save-Editor-GUI 你是否曾经在《塞尔达传说:旷…

2026/7/21 10:52:01阅读更多 →
从零手写C++ Actor框架:深入并发编程核心原理与工程实践

从零手写C++ Actor框架:深入并发编程核心原理与工程实践

1. 项目概述:为什么是Actor模型,为什么是C?如果你是一个有几年经验的C程序员,可能已经熟练掌握了STL容器、多线程同步、RAII这些基础技能,也写过一些并发程序。但当你面对一个需要处理海量并发连接、或者需要构建一个高…

2026/7/22 8:01:18阅读更多 →
win11跳过联网激活

win11跳过联网激活

shiftf10输入:start ms-cxh:localonly

2026/7/22 8:01:18阅读更多 →
Unity项目SSDLC实践:安全左移与质量内建的游戏开发流程

Unity项目SSDLC实践:安全左移与质量内建的游戏开发流程

1. 项目概述:为什么Unity项目需要SSDLC? 如果你是一个Unity开发者,或者正在管理一个Unity游戏或应用项目,你可能已经习惯了在Unity Hub里创建新项目、导入Asset Store资源、编写C#脚本、然后点击“Build”按钮。整个过程看起来流畅…

2026/7/22 8:01:18阅读更多 →
ICU护理实战:从生命体征监测到人文关怀的技术融合

ICU护理实战:从生命体征监测到人文关怀的技术融合

1. 护理工作的真实面貌:七分护理背后的生命重量 凌晨三点十七分,监护仪的报警声划破病房的寂静。吴瑛一个箭步冲到3床前,在医生到达前的黄金四分钟内完成了吸痰、调整氧流量、体位引流一系列操作。这不是影视剧里的场景,而是三甲医…

2026/7/22 8:01:18阅读更多 →
数据分析的重要性

数据分析的重要性

引言在当今信息爆炸的时代,数据成为了企业决策过程中的关键因素之一。无论是科技公司、制造行业还是服务业,正确有效地处理和解析大量数据已经成为了核心竞争力的一部分。因此,了解数据分析及其重要性显得尤为重要。什么是数据分析&#xff1…

2026/7/22 8:01:18阅读更多 →
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:ERP 企业资源模块,一个轻量级进销存的完整实现?

【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:ERP 企业资源模块,一个轻量级进销存的完整实现?

大家好,我是你们的源码拆解的腻害兔,今天继续 RuoYi-Vue-Pro(芋道)系列。前面我们已经拆了框架层、认证权限、多租户、工作流 BPM、支付、CRM 等模块,今天终于来到了很多读者翘首以盼的 ERP 企业资源模块。 为什么说是…

2026/7/22 7:59:18阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 0:53:59阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 0:53:59阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 0:53:59阅读更多 →
中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业小程序开发公司怎么选:预算、上手和售后避坑指南

中小企业做小程序,最常见的矛盾是预算有限,但又不希望功能太单薄;没有技术团队,但又希望后续能自己运营;想快速上线,又担心隐性收费和售后失联。选型时如果只看“低价套餐”或“案例数量”,很容…

2026/7/22 0:01:17阅读更多 →
GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

GEO优化如何沉淀长期内容资产?广拓时代谈AI搜索时代的内容ROI

企业做营销,最怕钱花完了,资产没有留下。 效果广告能带来一段时间的曝光,但预算停止后,流量往往也随之停止。短视频内容可能在几天内冲高,也可能很快沉下去。AI搜索时代,企业需要重新思考一个问题&#xff…

2026/7/22 0:01:17阅读更多 →
Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复

Agent 终态判定:何时该停止思考、给出最终回复 一、你的 Agent 在"再想想"的循环里绕了 12 轮,用户已经关窗口了 Agent 与人最大的区别是:人知道什么时候该停下来给答案,Agent 会一直"想"下去。你给 Agent 接…

2026/7/22 0:01:17阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/21 22:53:50阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →