0x01 前言
在服务器编程中,经常会遇到 Too many open files 这个报错,而且这个报错如果处理不好,很有可能会导致服务器死循环。
0x02 示例代码
以上是我用rust写的一个非常简单的tcp服务器,它的主要逻辑是,先创建一个listener,然后再在循环里不断调用listener.accept接收tcp连接,如果接收成功,就调用handle_client处理这个连接,如果接收失败,就打印一行错误日志。
handle_client里的逻辑也非常简单,就是等待客户端关闭连接,或等待其发送任意数据,当这两种情况发生时,handle_client就会直接关闭这个连接。
当然,如果在等待期间报错了,handle_client也会打印一行错误日志。
下面我们就会使用这段程序,来演示服务器死循环的情况,这段程序不必非要用rust编写,用其他语言也都可以。
测试代码我已经放到github了,如果想要自己动手测试的,可以clone下来自己试下。
代码地址:https://github.com/ytcoode/too-many-open-files
0x03 动手演示
先启动该服务器:
由上图可见,该服务器的进程id是312004,监听地址是0.0.0.0:9999。
再查看下该服务器已打开的文件数:
一共是10个,主要包括标准输入输出、epoll、及一些socket。
再查看下该服务器进程最多可打开的文件数:
看选中行,Soft Limit那一列,其表示该进程最多可用的文件描述符数量为1024个,即最多可同时打开的文件数为1024个。
我们把它改小一点,方便后续测试:
上图中,先使用prlimit命令将该服务器进程的Max open files数改成12,然后再用cat命令确认下该改动已生效。
至此,我们已经设置好该服务器进程最多可用的文件描述符数量为12,其当前已用的文件描述符数量为10,所以该服务器最多还可以再接收2个tcp连接。
我们用 `ncat localhost 9999` 命令建立连接试一下,当然你也可以用telnet, nc等其他命令,只要能建立tcp连接就行:
由上图服务器日志可见,该tcp连接已建立成功。