设为首页 收藏本站
查看: 498|回复: 0

[经验分享] ulimit限制之nproc问题

[复制链接]
累计签到:1 天
连续签到:1 天
发表于 2014-4-11 23:34:03 | 显示全部楼层 |阅读模式
这个问题挺有意思的,这里面有二个信息点:

1. 为什么limit配置文件是 /etc/security/limits.d/90-nproc.conf 而不是其他?
2. 为什么是nproc的值95044,而不是其他。

之前我也写了些ulimit的问题的解决,参见 这里

我们来简单的做下实验:



$ cat /etc/security/limits.d/90-nproc.conf         
*      soft    nproc   8933
$ ulimit -u
8933

$ cat /etc/security/limits.d/90-nproc.conf      #注释掉
#*      soft    nproc   8933
$ ulimit -u
385962
我们可以看出就是说当注释掉限制的话,不同的机器值是不同的。

我们先来回答第一个问题:为什么limit配置文件是 /etc/security/limits.d/90-nproc.conf 而不是其他
这个问题早些时候 杨德华 同学碰到了,也写了篇 博文 来解释redhat6下面如何破解nproc的限制,但是文章没提到这个问题。

我们一步步来看这个问题,首先看下 谁在使用 90-nproc.conf 这个文件:


$ cat t.stp
probe syscall.open.return {
  filename = user_string($filename)
  if (!isinstr(filename, "90-nproc.conf")) next;
  printf("%s %d\n", execname(), pid());
}
$ sudo stap t.stp
sshd 24844
运行脚本后,开个ssh终端上去,就马上知道sshd在使用这个文件, 同时也验证了配置是即刻生效的。

我们都知道linux下这个limit限制是由pam_limits来执行的。
那么什么是PAM以及它的架构,参考 这里



$ grep -rin pam_limit /etc/pam.d
/etc/pam.d/sudo-i:6:session    required     pam_limits.so
/etc/pam.d/smartcard-auth-ac:16:session     required      pam_limits.so
/etc/pam.d/smartcard-auth:16:session     required      pam_limits.so
/etc/pam.d/system-auth-ac:20:session     required      pam_limits.so
/etc/pam.d/fingerprint-auth:16:session     required      pam_limits.so
/etc/pam.d/sudo:6:session    required     pam_limits.so
/etc/pam.d/runuser:4:session            required        pam_limits.so
/etc/pam.d/password-auth-ac:19:session     required      pam_limits.so
/etc/pam.d/password-auth:19:session     required      pam_limits.so
/etc/pam.d/system-auth:20:session     required      pam_limits.so
/etc/pam.d/fingerprint-auth-ac:16:session     required      pam_limits.so
那很自然,我们就会去找pam_limits的代码来看, 代码在 这里 可以下载,目前的版本是 Linux-PAM-1.1.6。

瞄几下modules/pam_limits/pam_limits.c就知道 限制如何执行的:



/* now the session stuff */
PAM_EXTERN int
pam_sm_open_session (pam_handle_t *pamh, int flags UNUSED,
                     int argc, const char **argv)
{
[...]
   retval = init_limits(pamh, pl, ctrl);
    if (retval != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_WARNING, "cannot initialize");
        return PAM_ABORT;
    }

    retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
    if (retval == PAM_IGNORE) {
        D(("the configuration file ('%s') has an applicable '<domain> -' entry", CONF_FILE));
        return PAM_SUCCESS;
    }
    if (retval != PAM_SUCCESS || pl->conf_file != NULL)
        /* skip reading limits.d if config file explicitely specified */
        goto out;

    /* Read subsequent *.conf files, if they exist. */

    /* set the LC_COLLATE so the sorting order doesn't depend                                                            
        on system locale */

    oldlocale = setlocale(LC_COLLATE, "C");
    glob_rc = glob(LIMITS_CONF_GLOB, GLOB_ERR, NULL, &globbuf);

    if (oldlocale != NULL)
        setlocale (LC_COLLATE, oldlocale);

    if (!glob_rc) {
        /* Parse the *.conf files. */
        for (i = 0; globbuf.gl_pathv[i] != NULL; i++) {
            pl->conf_file = globbuf.gl_pathv[i];
            retval = parse_config_file(pamh, pwd->pw_name, pwd->pw_uid, pwd->pw_gid, ctrl, pl);
          if (retval == PAM_IGNORE) {
                D(("the configuration file ('%s') has an applicable '<domain> -' entry", pl->conf_file));
                globfree(&globbuf);
                return PAM_SUCCESS;
            }
            if (retval != PAM_SUCCESS)
                goto out;
        }
    }

out:
[...]
}
分析这段代码可以知道先读/etc/security/limits.conf,如果/etc/security/limits.d/目录下还有配置文件的话,也读进来,一起分析。
这就意味/etc/security/limits.d/里面的文件里面的配置会覆盖/etc/security/limits.conf的配置。

我们看下这行:glob_rc = glob(LIMITS_CONF_GLOB, GLOB_ERR, NULL, &globbuf);
读取/etc/security/limits.d/目录下文件的函数,从名字就可以猜出,是遍历,文件名的数字起到顺序的作用。

到此就解释了文件名90-nproc.conf的作用。

接着看第二个问题: 为什么是nproc的值95044, 而不是其他。
通过阅读process_limit函数只是看到 nproc的最大值限制,没有看到其他的,那我们就很容易联想,如果用户不设置nproc的话,那么这个值应该是由内核自己来决定。

我们看下内核代码 2.6.18:



$ pwd
/home/chuba/linux-2.6.18.x86_64/kernel
$ grep -rin nproc .
./sys.c:896:                            current->signal->rlim[RLIMIT_NPROC].rlim_cur &&
./fork.c:176:   init_task.signal->rlim[RLIMIT_NPROC].rlim_cur = max_threads/2;
./fork.c:177:   init_task.signal->rlim[RLIMIT_NPROC].rlim_max = max_threads/2;
./fork.c:179:           init_task.signal->rlim[RLIMIT_NPROC];
./fork.c:1130:                  p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
./cpuset.c:69:  int cnt;                /* unprocessed events count */
./cpuset.c:1140: * Limit the count of unprocessed events to FM_MAXCNT, so as to avoid
./user.c:181:    * new uid over his NPROC rlimit?  We can check this now
一下子就看出来了 默认值是 max_threads/2. 打开fork.c分析下:

//fork_init(num_physpages);
//void __init fork_init(unsigned long mempages)
/*
* The default maximum number of threads is set to a safe
* value: the thread structures can take up at most half
* of memory.
*/
max_threads = mempages / (8 * THREAD_SIZE / PAGE_SIZE);

其中mempages是机器的物理页面个数, THREAD_SIZE=8K, 也就是说:

default_nproc = max_threads / 2 = (mempages * PAGE_SIZE) / ( 2 * 8 *THREAD_SIZE ) = total_memory/128K;

我们来验证下:



$ cat /proc/meminfo |grep MemTotal
MemTotal:       49421024 kB
$ echo "49421024 / 128"| bc
386101
$ ulimit -u
385962
算出来default_nproc =386101 是不是和实际的很接近?
因为物理页面会内存用作一些关键数据,所以实际的比计算出来的要小点。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-17216-1-1.html 上篇帖子: 在linux下搭建DHCP和DHCP中继 下篇帖子: ulimit问题 关于nproc设置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表