你真知道“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”作为出发点

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

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

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

同志们,重点又来了。rlimit(RLIMIT_NOFILE)这个函数得到的是soft nofile,我们继续看__alloc_fd

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:

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(为了节省版面,完整的代码图我附在后面)

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不在内核代码中它有自己独立的代码仓库,为了做有良知的自媒体我是不是特别拼?)

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

作者:邢森

来源:51CTO

时间: 2024-09-20 20:56:55

你真知道“Too many open files”?的相关文章

php使用glob函数遍历文件和目录详解_php技巧

php glob()函数返回匹配指定模式的文件名或目录.因此我们可以使用glob函数来查找文件,也可以实现目录的遍历. 函数说明:array glob ( string $pattern [, int $flags ] ) 功能:寻找与模式匹配的文件路径,返回包含匹配文件(目录)的数组(注:被检查的文件必须是服务器系统的,不能用于远程文件) 参数说明:第一个参数:匹配模式:第二个可选参数: GLOB_MARK - 在每个返回的项目中加一个斜线 GLOB_NOSORT - 按照文件在目录中出现的原

Xcode 5.1 编译模拟器以及真机都能使用的静态库

Xcode 5.1.dmg 下载地址 http://pan.baidu.com/s/1jGJpKm6   1.新建 Framework & Library 工程 我起名叫ShowInfo,下面为其源码 showInfo.h ========================= #import <Foundation/Foundation.h> @interface ShowInfo : NSObject + (void)showInfo; @end ===================

iOS程序完成后如何生成ipa进行真机测试,签名

1.identifier com.for.ever(自定义,与证书相同) 2.build setting -code signing 全选证书 3.clean project 4.iOS device -build 5.生成app 6.app-show in finder 7.itunes-拖进来(iPad应用程序)-show in finder 如何进行真机测试? 需要得到apple官方的development授权,过程如下 1.访问https://developer.apple.com/de

iOS开发:创建真机调试证书

方法/步骤 1 首先打开苹果的开发者网站(Tips:这里我就不贴网址了) 点击网站上方的Member Center,会跳转到登录界面(Tips:如果登录过,并选择了浏览器保存此密码的时候,默认是登录状态). 2 如图所示输入你的开发者账号和密码. 输入完成后点击"Login"(Tips:左边是注册,下边是找回密码,右边是登录,如果没有开发者账号,则需要用苹果账号申请开发者,这里不多说申请过程以及找回过程). 3 登录后的界面如图所示,如果没有最上面的两个选项(Dev Centers.C

在Eclipse的DDMS中的File Explorer找不到files文件夹

问题描述 在Eclipse的DDMS中的File Explorer找不到files文件夹 尝试着想用openFileOutput方法存储信息,本来应该能在data/data/../file文件夹中找到我存储的文件,却发现没有file文件夹,只有cache和lib文件夹,这是为什么? 以下是代码: public void Save(String text){ FileOutputStream out = null; BufferedWriter writer = null; try{ out =

华为智真远程会诊解决方案为医疗行业开创新格局

在2013年安捷信合作伙伴 大会上,华为领先的智真远程会诊解决方案为合作伙伴做了精彩展示,也为当前医疗行业的信息化建设.社会医疗改革提供了更加 先进的思路,也为普通百姓的求医问诊与健康保障提供了全 新的服务模式.华为智真远程会诊解决方案在华为视频通信系统的基础上,紧密结合医疗行业专业医学影像阅览.多种医疗设备对接.便捷式移动会诊等需求,提供远程会诊.手术示教.医疗教学.移动查房等应用,助力医疗行业信息化的 快速发展.498)this.w idth=498;' onmousewheel = 'ja

android studio真机调试 程序安装位置?

问题描述 android studio真机调试 程序安装位置? android studio真机调试 ,找不到程序的安装位置. Log.i("sbsb",getApplicationContext().getFilesDir().getAbsolutePath()); 结果为:/data/data/com.sbsb.photoupload/files 但是手机中并不存在这个路径..这是怎么回事? 解决方案 有的文件在电脑上就是看不到,你服不服 解决方案二: Android Studio

iOS开发PCH文件、NSLog真机不打印

添加PCH文件 现在Xcode6.7创建一个新的工程时将默认不会再带有PCH文件,需要手动添加PCH文件. 在Supporting Files目录下,选择 File > New > File > iOS > Other > PCH File 然后点击下一步进行命名,建议命名格式为项目名称-Prefix,如图Demo 创建的PCH文件与编译器Xcode进行连接:找到 Project > Build Settings > 搜索 "Prefix Header&

HBuilder真机联调iPhone手机设备问题

在windows上首先需要安装最新版本的itunes,并且让手机与itunes是相连的. 然后我们点击在XX手机设备上连接时,发现安装进度到32%就消失了,一开始还 不知道是怎么回事呢!原来是个BUG,官方给出的解决方法是: Q:真机联调的iOS设备连不上?A:真机联调需要调用iTunes的API,请确认iTunes正确安装,且手机可以正常连接到iTunes. 如果手机可以正常连接到iTunes则一般情况为iTunes的SQLite3.dll与系统自带的冲突了,解决方案如下: 1.64位系统打开