ulimit -s 仅修改当前 shell 会话的软栈限制,重启失效且不跨会话;硬限制由系统配置控制,普通用户无法提升;永久生效需配置 /etc/security/limits.conf 或 systemd service 的 LimitSTACK。

ulimit -s 能改的只是当前 shell 会话的栈限制
执行 ulimit -s 16384 确实能把当前终端里新启动进程的栈上限设为 16MB,但它只影响该 shell 启动的子进程,且重启终端就失效。常见错误是以为改完它就全局生效了——其实连同一台机器上另一个 ssh 登录的 session 都不受影响。
真正起作用的是软限制(soft limit)和硬限制(hard limit)两层机制:ulimit -s 默认修改软限制,而软限制不能超过硬限制;硬限制通常由系统级配置控制,普通用户无法自行提高。
- 用
ulimit -s查当前软限制,ulimit -Hs查硬限制 - 若想临时提硬限制,需 root 权限:
sudo ulimit -Hs 32768 - 软限制设得再高,如果硬限制卡在 8192,最终仍被截断
/etc/security/limits.conf 是永久生效的关键文件
要让某个用户(或所有用户)每次登录都获得指定栈大小,必须编辑 /etc/security/limits.conf。注意:这个文件不被 bash 的 ~/.bashrc 加载,也不是 systemd 服务的直接配置源。
典型写法(以用户 appuser 为例):
* soft stack 16384 * hard stack 32768
或限定单个用户:
appuser soft stack 16384 appuser hard stack 32768
- 单位始终是 KB,不是 MB 或字节
- 改完需重新登录(不是
source,不是systemctl daemon-reload) - SSH 登录、图形界面登录、
su -均生效;但直接su(不带-)不会触发 PAM limits 模块加载 - 某些发行版(如较新 Ubuntu)默认禁用
limits.conf,需确认/etc/pam.d/common-session中有session required pam_limits.so
systemd 服务的栈限制必须单独配置
如果你用 systemctl start myapp.service 启动程序,limits.conf 对它完全无效——systemd 绕过了 PAM limits。必须在 service 文件里显式声明:
[Service] LimitSTACK=16384
注意:LimitSTACK 单位是 KB,和 ulimit -s 一致;值为 infinity 表示不限制(等价于 ulimit -s unlimited)。
- 修改后必须
sudo systemctl daemon-reload,再sudo systemctl restart myapp -
LimitSTACK只作用于该 service 的主进程及其 fork 出的子进程,不影响其他服务 - 若服务使用
Type=notify或Type=forking,确保主进程是真正受控的那个 PID
pthread 创建线程时的栈大小是另一套机制
即使系统级栈限制设得很大,单个线程的栈空间仍由创建时指定,默认通常是 8MB(getrlimit(RLIMIT_STACK, &rl) 返回的值)。若你在程序里用 pthread_create,可以主动控制每个线程的栈:
pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 4 * 1024 * 1024); // 4MB pthread_create(&tid, &attr, thread_fn, NULL); pthread_attr_destroy(&attr);
-
pthread_attr_setstacksize的参数单位是字节,不是 KB - 值必须是系统页大小(
getpagesize())的整数倍,否则pthread_create返回EINVAL - 不能超过进程的
RLIMIT_STACK限制,否则创建失败 - 主线程的栈大小由
ulimit -s或limits.conf决定,不走 pthread 接口
最易被忽略的一点:线程栈大小设置和进程栈限制是两层独立约束,必须同时满足。哪怕 ulimit -s 放开了,pthread_attr_setstacksize 设得太大仍可能失败;反之,limits.conf 限制太严,即使代码里设小了,也可能因内核拒绝分配而 crash。调试时建议先用 cat /proc/<pid>/status | grep Stack 确认实际分配值。


















