天下遇到过Toomanyopenfiles错误(不管你是多线程,networksocket,还是其他的飞蛾扑火,这个错误都很常见)。笔者的一个朋友刚遇到,经过一番查找,终于解决了这个问题。但是我还是没有想通——“问题出在哪里?”。当然我也解释不清楚(不然就没有这篇文章了),网上也找不到相关资料。作为一个有良心的自媒体公众号,决定为大家深究一下这个问题。(用了两个晚上~~,记得打赏一下)网上流传的三种方法:修改ulimit命令修改,这个修改只在当前session有效或者/etc/security/limits.conf设置hardsoftnofile,即可Alwayseffectivesysctlmodifyfs.file-maxmodify/proc/sys/fs/nr_open(optional)也有传说这个有优先级-limit.confnext_fd);该进程当前可用(fd位图fdt->max_fds中没有设置flag);进程扩展(fd位图不存在,需要执行expand_files扩展fd位图),所以__alloc_fd函数分三步尝试分配fd。Tryto"pre-allocate"fd(directallocation)Trytoallocate"available"fd(needtofillbitmap)Trytoexpandfdbitmapsize如果fd超过softnofile,这个函数会直接返回"error"。所以softnofile是fdsizelimit的第一层,hardnofile自始至终都没用。softnofile的确切含义是——当前可以使用多少fd。目前是和“流程”相关的,详见上篇。我们继续看“扩展”fd:fs.nr_open是文件描述符的最后一层。当我们试图扩展文件描述符时,只要你不比它大,系统就允许你扩展。它的最大值是2147483584。结论:softnofile和fs.nr_open是用来控制文件描述符个数的。softnofile其实是由linux的pam_limit模块设置的。如果不启用该模块,只能通过ulimit命令进行调整。如果不把它的值调整为4096(可以看***代码图)nr_open表示最大文件描述符数。它的最大值是2147483584(在64位机器上是2^31-64)。这也是softnofile和fs.nr_open可以设置的最大值。文件结构文件描述符在内核中其实是一个数字,代表一个“索引”,索引的内容就是“文件结构”(内核数据结构structfile)。内核在分配资源时,将“index”和“content”分配为两个资源。先申请“索引”,再申请“内容”。跳回sock_map_fd看第二步——分配文件结构,调用sock_alloc_file函数。跟着这个函数你会发现-file-max(为了节省篇幅,附上完整的代码图)file-max指的是structfile的上限。可以把softnofile和fs.nr_open设置成天文数字,但是不设置file-max就意味着structfile不能分配,文件描述符没用,资源分配还是不成功。(像12306,抢不到票还是要“排队”,抢到的只是一个占位符,可能被***“丢票”了。是的,我没买票,等大家众筹票好了。)总结:fs.file-max用于控制文件结构数量等。三个参数的真正含义在结束前已经扒出来了,但是作为一个有良心的自媒体公众号必??须要讲清楚真相。于是就挖出了软nofile的前世今生。PAM(PluggableAuthenticationModules)是Linux的身份验证框架。系统启动成功后,后台服务进程和bash都会通过setup_limits加载/etc/security/limit.conf文件,然后调用setrlimit重置进程的rlimt——包括softnofile。(pam_limit不在内核代码里,有自己独立的代码仓库,为了做一个有良心的自媒体,我辛苦了吗?)ulimit命令其实是系统内部命令(不信你打哪个ulimit)。也是通过调用setrlimit设置完成的。两者的区别是pam_limit是自动加载的(属于linux的“认证模块”),ulimit需要手动输入命令。【本文为专栏作者邢森原创文章,转载请联系作者获得授权】