发布于2026-07-01 阅读(0)
扫一扫,手机访问
Linux 内核的信号处理机制看似底层,实际工作中经常卡在几个配置点上。很多人以为调信号限制得改内核参数或挂载 sysctl,其实真正需要动手的地方在用户空间的资源限制层——ulimit 和 systemd 的单元配置,以及你代码里怎么用备用栈。

内核信号处理限制不能通过内核模块或sysctl直接配置,必须从用户空间资源限制(ulimit)和内核编译/启动参数两层入手,核心是控制RLIMIT_SIGPENDING和信号栈大小。
这么说可能有点抽象,我们先把关键概念拆开看。
每个进程到底能排多少信号在队列里等着处理?这个数字由 RLIMIT_SIGPENDING 控制,对应 ulimit -i 的输出。
ulimit -i 显示当前 shell 会话下进程可以挂起的信号数量上限——也就是RLIMIT_SIGPENDING的软限制。ulimit -Hi 看硬限制,硬限制只能 root 改。sigqueue() 发送带数据的实时信号,而 ulimit -i 设得太低,你就会看到 errno = EAGAIN(信号队列满了)。很多人误以为是内存不足,其实排查方向完全错了。调试时或临时扩容,可以在启动服务前用 ulimit 调一把。不过要注意作用域——只影响当前 shell 及其子进程。
ulimit -i 2048sudo ulimit -Hi 4096对于长期跑的守护进程,必须显式地在单元文件里声明限制,否则系统默认值(通常是 122880)会一直生效。
/etc/systemd/system/myapp.service[Service] 段添加一行:LimitSIGPENDING=8192sudo systemctl daemon-reload && sudo systemctl restart myappsystemctl show myapp.service | grep SIGPENDING,或者直接看进程的 /proc/PID/status 里的 SigQ 字段。SA_ONSTACK场景)当主线程栈快用尽时,你可能会用备用栈来处理信号(比如捕获 SIGSEGV 做最后手脚)。这时栈空间够不够用就很关键。
ulimit -s,单位是 KB。它对应 RLIMIT_STACK,也影响信号备用栈的大小。sigaltstack() 设置信号专用栈时,最大可用空间受 ulimit -s 约束。如果你设得比这个值还大,调用会失败。signal handler returned, but stack overflow detected,说明备用栈溢出了。解决办法是增大 ulimit -s,同时检查 sigaltstack.ss_size 是否合理。最后说一个容易掉坑的点:信号队列限制(RLIMIT_SIGPENDING)是按用户汇总统计的,不是单进程隔离。这意味着一个进程狂发信号,可能会拖累整个用户的所有进程。而且 sigqueue() 失败时返回的是 EAGAIN 而不是 ENOMEM,排查时第一反应很容易往内存方向跑偏,白费不少时间。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
4
5
6
7
8
9