转载

你真知道 “Too many open files” ?

江湖上的人都碰到过 Too many open files 的错误(无论你是多线程,网络socket,还是别的什么幺蛾子,这个错误很常见)。笔者一个朋友刚好也碰到过,经过一番搜索最终解决了问题。但是始终没有搞清楚——“到底问题出在哪里?”。我当然也讲不清楚(否则就不会有这篇文章咯)网上也找不到相关资料。作为一个 有良知的自媒体公众账号 ,我决定要把替大家去深究一下这个问题。(花了两个晚上~~,记得打赏我)

网上流传的三种做法:

  • 修改ulimit命令修改,这种修改只能在当前会话有效或者/etc/security/limits.conf设置hard soft nofile,可以一直有效

  • sysctl修改fs.file-max

  • 修改/proc/sys/fs/nr_open(可选)

还有一种传说这是有优先级的——limit.conf < fs.file-max < nr_open 然而这都是 扯淡 ,纯粹的臆想。 有良知的自媒体公众账号 是讲道理的,正所谓—— 没代码你说个屁啊!!! ;所以我就顺着Linux Kernel的代码挖了下去。

Linux/Unix一个著名的哲学就是——“万物皆文件”,无论是一个线程、socket、还是真正的文件都会被当做“文件”。 Too may open files 通常意味着“文件描述符”不足,它一般会发生在“创建线程”、“创建socket”、“打开文件”这种场景下。我选“创建socket”作为出发点

文件描述符的限制?不对!!

你真知道 “Too many open files” ?

调用 socket 函数的时候内核会分两步操作——填充数据结构,分配fd。我们重点看 socket_map_fd

你真知道 “Too many open files” ?

关键的地方来了, get_unused_fd_flags 会尝试分配一个fd,但是这个仅仅是fd——是一个数字而已;就是我们常说的——文件描述符。仅仅有一个数字并不代表什么,它相当于一个占位符,系统并没有实际的分配资源。 socket_alloc_file 才是真正的建立 文件结构 (内核的数据结构: struct file )。打开get_unsed_fd_flags摸下去:

你真知道 “Too many open files” ? 同志们,重点又来了。 rlimit(RLIMIT_NOFILE) 这个函数得到的是 soft nofile ,我们继续看 __alloc_fd

你真知道 “Too many open files” ?

fd备用有三部分组成,进程当前预分配的(fd位图中设置了标记,fdt->next_fd);进程当前可用的(fd位图中没有设置标记,fdt->max_fds);进程扩展的(fd位图中都不存在,需要执行expand_files扩展fd位图)所以 __alloc_fd 函数分为了三步尝试分配fd。

  • 尝试“预分配”的fd(直接分配)

  • 尝试分配“可用的”的fd(需要填充位图)

  • 尝试扩展fd位图大小

如果fd超过soft nofile,这个函数会直接返回“错误”。所以soft nofile是fd大小限制的第一道关卡,hard nofile全程没用。soft nofile的准确而含义是——当前可以使用多少fd 当前是跟“进程”有关系的,详细内容请看最后一部分。我们继续看“扩充”fd:

你真知道 “Too many open files” ? fs.nr_open是文件描述符的最后一道关卡,当我们尝试扩充文件描述符的时候只要你不大于它系统就允许你扩充 ,它的最大值是2147483584。 结论:

  • soft nofile、fs.nr_open是用来控制文件描述符数量的

  • soft nofile其实是linux的pam_limit模块设置的如果你不启用这个模块,你只能通过ulimit命令调整。如果不调整它的值是4096(可以看最后的代码图)

  • nr_open表示文件描述符最大数量。它的最大值是 2147483584 (64位机器上2^31-64)。这也是是soft nofile、fs.nr_open可以设置的最大值。

文件结构体

文件描述符在内核中其实是一个数字,它代表的是一个“索引”而索引的内容是“文件结构体”(内核数据结构  struct file )。内核分配资源的时候把“索引”和“内容”当做两种资源来分配。先申请“索引”后申请“内容”。跳回 sock_map_fd 看第二步——分配 文件结构 ,它调用了 sock_alloc_file 函数。 顺着这个函数走下去你会发现—— file-max (为了节省版面,完整的代码图我附在后面) 你真知道 “Too many open files” ? file-max是指struct file的上限。你可以把soft nofile、fs.nr_open设置成天文数字,但是不设置file-max就意味着没法分配struct file,文件描述符就没用了,依旧资源分配不成功。(像12306,你抢到票还不行还得“排队”。抢到的仅仅是一个占位符,到最后可能“没票了”。对,我没买到车票,等大家众筹机票了。) 总结:

  • fs.file-max是用来控制 文件结构体 数量的

等等,还没结束

上面已经扒出了三个参数的真实意义,但是作为一个—— 有良知的自媒体公众号 必须把道理讲清楚。所以我就挖出了soft nofile的前生今世。 PAM(Pluggable Authentication Modules)是Linux的认证框架,在系统启动成功后无论是后台服务进程还是bash都会通过setup_limits加载/etc/security/limit.conf文件然后调用 setrlimit 重新设置进程的rlimt——其中就包括了soft nofile。(pam_limit不在内核代码中它有自己独立的代码仓库,为了做有良知的自媒体我是不是特别拼?) 你真知道 “Too many open files” ?

ulimit这个命令其实是系统的内部命令(不信你打which ulimit)它也是调用 setrlimit 完成的设置。二者的区别是pam_limit是自动加载的(属于linux的“认证模块”),ulimit你必须动手输入命令。

我用心绘制的代码图

我绘制的高清无码图片都被无情的压缩“马赛克版了”所以只能放在七牛云上了(一共7-8M左右)

  • 总图 http://o83khlyy2.bkt.clouddn.com/linux_code/%E6%80%BB%E5%9B%BE.png

  • sysctl_nr_open的前生今世 http://o83khlyy2.bkt.clouddn.com/linux_code/sysctl_nr_open%E7%9A%84%E5%89%8D%E7%94%9F%E4%BB%8A%E4%B8%96.png

  • soft nofile的前生.png http://o83khlyy2.bkt.clouddn.com/linux_code/soft%20nofile%E7%9A%84%E5%89%8D%E7%94%9F.png

  • soft nofile的今世 http://o83khlyy2.bkt.clouddn.com/linux_code/soft%20nofile%E7%9A%84%E4%BB%8A%E4%B8%96.png

欢迎关注公众账号了解更多信息“写程序的康德——思考、批判、理性”

你真知道 “Too many open files” ?

原文  http://mp.weixin.qq.com/s?__biz=MzIxMjAzMDA1MQ==&mid=2648945736&idx=1&sn=9aa7c240408dd84c4f9d48681f1ec18d&chksm=8f5b5344b82cda52d499cb300514d2b89b0fe6080daeb2bfddcfec427b8b02b4fb9eed4c0fab
正文到此结束
Loading...