Linux对能够打开的文件句柄的数量做了限制。限制是分为三个层面:
系统层面、用户层面、进程层面。
如果某个进程打开的文件句柄超过限制,再打开文件就会报错。
Too many open files 或者 Socket/File: Can’t open so many files
因此,在编程时,如果进程要占用大量文件句柄的话,就要看看是否要调整最大可打开的文件句柄数,同时也要注意close释放掉不用的文件句柄。
查看文件句柄数限制
系统层面
[root@anolis ~]# cat /proc/sys/fs/file-max
376093
用户层面
# ulimit -n
1024
进程层面
ps -ef|grep java
root 3146 1 3 09:54 ? 00:10:08 /usr/local/jdk1.8.0_11/bin/java -server -jar /usr/local/tomcat/qhdzs/qhd_private.jar --spring.profiles.active=test
cat /proc/3146/limits
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size 8388608 unlimited bytes
Max core file size 0 unlimited bytes
Max resident set unlimited unlimited bytes
Max processes 15591 15591 processes
Max open files 4096 4096 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 15591 15591 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Max open files 4096 4096 files
这就是进程级别的打开文件句柄数量限制
系统级限制
理论上系统内存有多少就可以打开多少的文件句柄,但是在实际中内核是会做相应的处理,一般最大打开文件数会是系统内存的10%(以KB来计算),称之为系统级限制。这个数字可以通过 cat /proc/sys/fs/file-max 或者 sysctl -a | grep fs.file-max 命令查看。
更改系统级限制有临时更改和永久更改两种方式:
临时更改:
session断开或者系统重启后会恢复原来的设置值。使用命令 sysctl -w fs.file-max=xxxx,其中xxxx就是要设置的数字。
永久更改:
vim编辑 /etc/sysctl.conf 文件,在后面添加 fs.file-max=xxxx,其中xxxx就是要设置的数字。保存退出后还要使用sysctl -p 命令使其生效。
用户级限制
同时为了控制每个进程消耗的文件资源,内核也会对单个进程最大打开文件数做默认限制,即用户级限制。32位系统默认值一般是1024,64位系统默认值一般是65535,可以使用 ulimit -n 命令查看。
更改用户级限制也有临时更改和永久更改两种方式:
临时更改:
session断开或者系统重启后会恢复原来的设置值。使用命令 ulimit -SHn xxxx 命令来修改,其中xxxx就是要设置的数字。
永久更改:
vim编辑 /etc/security/limits.conf 文件,修改其中的 hard nofile xxxx 和 soft nofile xxxx,其中xxxx就是要设置的数字。保存后退出。关于hard和soft的区别,参照下面参考链接中的第5个。
文件句柄数最大值和影响最大值的因素
在Linux下,系统全部能够打开的fd(文件句柄)总数为:/proc/sys/fs/file-max,取决于内存
# The file-max parameter
# file-max参数
The file-max file /proc/sys/fs/file-max sets the maximum number of file-handles that the Linux kernel will allocate. We generally tune this file to improve the number of open files by increasing the value of /proc/sys/fs/file-max to something reasonable like 256 for every 4M of RAM we have: i.e. for a machine with 128 MB of RAM, set it to 8192 - 128/4=32 32*256=8192.
# file-max file /proc/sys/fs/file-max设置Linux内核将分配的最大文件句柄数量。我们通常通过将/proc/sys/fs/file-max的值增加到一个合理的值来调整这个文件,比如每4M内存增加256个文件;也就是说,对于一台有128MB内存的机器,将其设置为8192 128M/4M=32个 32*256=8192.
The default setup for the file-max parameter under Red Hat Linux is: "4096" To adjust the value of file-max to 128 MB of RAM, type the following on your terminal:
# Red Hat Linux下file-max参数的默认设置是“4096”要将file-max的值调整为128MB 内存,需要在终端执行以下命令
[root@deep] /# echo "8192" >/proc/sys/fs/file-max
Add the above commands to the /etc/rc.d/rc.local script file and you'll not have to type it again the next time your server reboots.
# 将上述命令添加到/etc/rc.d/rc.local脚本文件中,下次服务器重新启动时,就不必再执行它了。
Edit the /etc/sysctl.conf file and add the following line:
编辑 /etc/sysctl.conf 文件并添加以下行:
# Improve the number of open files
fs.file-max = 8192
You must restart your network for the change to take effect. The command to manually restart the network is the following:
# 必须重启网络,以使得更改生效。重启网络的命令如下:
[root@deep] /# /etc/rc.d/init.d/network restart
Setting network parameters [ OK ] Bringing up interface lo [ OK ] Bringing up interface eth0 [ OK ] Bringing up interface eth1 [ OK ]
When you regularly receive from your server a lot of messages with errors about running out of open files, you might want to raise this limit. The default value is 4096. A file server or web server needs a lot of open files
# 当你经常从服务器收到大量关于打开文件不足的错误消息时,就需要提高此限制,默认值为4096,文件服务器或者web服务器需要大量的打开文件。
文献资料来自:http://www.faqs.org/docs/securing/chap6sec72.html
[root@anolis ~]# free -m
total used free shared buff/cache available
Mem: 3720 227 3235 8 257 3267
Swap: 4043 0 4043
3720/4=930 930*256=238080
这台服务器上的 fs.file-max参数的理论最大值可以设置为238080。
用户级别限制/etc/security/limits.conf
对linux某个用户设置系统资源,我们都已经知道可以用ulimit命令来查看和设置。
limits.conf 文件实际是 Linux PAM(插入式认证模块,Pluggable Authentication Modules)中 pam_limits.so 的配置文件,而且只针对于单个会话。
格式如下:
username|@groupname type resource limit
username|@groupname:设置需要被限制的用户名,组名前面加@和用户名区别。也可以用通配符*来做所有用户的限制。
type:有 soft,hard 和 -,soft 指的是当前系统生效的设置值。hard 表明系统中所能设定的最大值。soft 的限制不能比har 限制高。用 - 就表明同时设置了 soft 和 hard 的值
resource:
core - 限制内核文件的大小
date - 最大数据大小
fsize - 最大文件大小
memlock - 最大锁定内存地址空间
nofile - 打开文件的最大数目
rss - 最大持久设置大小
stack - 最大栈大小
cpu - 以分钟为单位的最多 CPU 时间
noproc - 进程的最大数目
as - 地址空间限制
maxlogins - 此用户允许登录的最大数目
要使 limits.conf 文件配置生效,必须要确保 pam_limits.so 文件被加入到启动文件中。
查看 /etc/pam.d/login 文件中有:
session required /lib/security/pam_limits.so
暂时地,适用于通过 ulimit 命令登录 shell 会话期间。
永久地,通过将一个相应的 ulimit 语句添加到由登录 shell 读取的文件之一(例如 ~/.profile),即特定于 shell 的用户资源文件;或者通过编辑 /etc/security/limits.conf。
何谓core文件,当一个程序崩溃时,在进程当前工作目录的core文件中复制了该进程的存储图像。core文件仅仅是一个内存映象(同时加上调试信息),主要是用来调试的。 core文件是个二进制文件,需要用相应的工具来分析程序崩溃时的内存映像。
系统默认core文件的大小为0,所以没有创建。可以用ulimit命令查看和修改core文件的大小。
ulimit -c 1000
$ ulimit -c
1000
-c 指定修改core文件的大小,1000指定了core文件大小。也可以对core文件的大小不做限制,
如:
ulimit -c unlimited
ulimit -c
unlimited
如果想让修改永久生效,则需要修改配置文件,如 .bash_profile、/etc/profile或/etc/security/limits.conf。
2.nofile - 打开文件的最大数目
对于需要做许多套接字连接并使它们处于打开状态的应用程序而言,最好通过使用 ulimit –n,或者通过设置nofile 参数,为用户把文件描述符的数量设置得比默认值高一些。
vi /etc/security/limits.conf
- soft nofile 10240 #软限制
- hard nofile 10240 #硬限制
用ulimit -n 2048 修改只对当前的shell有效,退出后失效:
如A程序已经运行,此时ulimit -n为1024;之后ulimit -n 2048,这时在运行B程序;退出当前shell用户,再次进行shell,之后运行C程序;这时只有B程序用的是2048,其它用的都是1024。
ulimit:显示(或设置)用户可以使用的资源的限制(limit),这限制分为软限制(当前限制)和硬限制(上限),其中硬限制是软限制的上限值,应用程序在运行过程中使用的系统资源不超过相应的软限制,任何的超越都导致进程的终止。
参数 描述
ulimited 不限制用户可以使用的资源,但本设置对可打开的最大文件数(max open files)
和可同时运行的最大进程数(max user processes)无效
-a 列出所有当前资源极限
-c 设置core文件的最大值.单位:blocks
-d 设置一个进程的数据段的最大值.单位:kbytes
-f Shell 创建文件的文件大小的最大值,单位:blocks
-h 指定设置某个给定资源的硬极限。如果用户拥有 root 用户权限,可以增大硬极限。任何用户均可减少硬极限
-l 可以锁住的物理内存的最大值
-m 可以使用的常驻内存的最大值,单位:kbytes
-n 每个进程可以同时打开的最大文件数
-p 设置管道的最大值,单位为block,1block=512bytes
-s 指定堆栈的最大值:单位:kbytes
-S 指定为给定的资源设置软极限。软极限可增大到硬极限的值。如果 -H 和 -S 标志均未指定,极限适用于以上二者
-t 指定每个进程所使用的秒数,单位:seconds
-u 可以运行的最大并发进程数
-v Shell可使用的最大的虚拟内存,单位:kbytes
[root@server-mysql fs]# ulimit -n unlimited
-bash: ulimit: open files: cannot modify limit: Operation not permitted
[root@server-mysql fs]#
[root@server-mysql fs]# ulimit -n 1048576
[root@server-mysql fs]# ulimit -n 1048577
-bash: ulimit: open files: cannot modify limit: Operation not permitted
[root@server-mysql fs]# cat /proc/sys/fs/nr_open
1048576
[root@server-mysql fs]# echo 1000000 > /proc/sys/fs/nr_open
[root@server-mysql fs]# cat /proc/sys/fs/nr_open
[root@server-mysql fs]# ulimit -n 999999
[root@server-mysql fs]# ulimit -n 1000000
[root@server-mysql fs]# ulimit -n 1000001
-bash: ulimit: open files: cannot modify limit: Operation not permitted
[root@server-mysql fs]# cd /proc/sys/fs/
[root@server-mysql fs]# cat file-nr
2496 0 132022
[root@server-mysql fs]# cat file-max
132022
[root@server-mysql fs]# echo 2000000 >file-max
[root@server-mysql fs]# cat file-nr
2496 0 2000000
man 5 proc:
/proc/sys/fs/file-max
This file defines a system-wide limit on the number of open files for all processes. (See
also setrlimit(2), which can be used by a process to set the per-process limit,
RLIMIT_NOFILE, on the number of files it may open.) If you get lots of error messages about
running out of file handles, try increasing this value:
echo 100000 > /proc/sys/fs/file-max
The kernel constant NR_OPEN imposes an upper limit on the value that may be placed in file-
max.
If you increase /proc/sys/fs/file-max, be sure to increase /proc/sys/fs/inode-max to 3-4
times the new value of /proc/sys/fs/file-max, or you will run out of inodes.
/proc/sys/fs/file-nr
This (read-only) file gives the number of files presently opened. It contains three num-
bers: the number of allocated file handles; the number of free file handles; and the maximum
number of file handles. The kernel allocates file handles dynamically, but it doesn’t free
them again. If the number of allocated files is close to the maximum, you should consider
increasing the maximum. When the number of free file handles is large, you’ve encountered a
peak in your usage of file handles and you probably don’t need to increase the maximum.
ulimit其实就是对单一程序的限制,进程级别的
系统总限制:/proc/sys/fs/file-max
通过 man 5 proc 找到file-max的解释:
file-max指定了系统范围内所有进程可以打开的文件句柄的数量限制---kernel-level
可以通过cat查看目前的值,echo来立刻修改
echo 10000 > /proc/sys/fs/file-max
另外还有一个,/proc/sys/fs/file-nr
只读,可以看到整个系统目前使用的文件句柄数量
写一个简单的for循环得出:
for v in `seq 100000 10000000`;do ulimit -n $v; [[ $? != 0 ]]&&break;done
再执行ulimit -n ,可以看到1048576就是nofile的最大值了,但为什么是这个值?1048576是1024*1024,当然这并没有什么卵用。。。再跟踪一下我们就会发现这个值其实是由内核参数nr_open定义的:
进程级打开的最大文件数的限制/proc/sys/fs/nr_open
cat /proc/sys/fs/nr_open
1048576
到此我们就要说起nr_open,与file-max了,网上在说到设置最大文件数时偶尔有些帖子也说到要修改file-max,字面上看file-max确实像是对应最大文件数,而在linux内核文档中它们两的解释是:
The value in file-max denotes the maximum number of file-
handles that the Linux kernel will allocate. When you get lots
of error messages about running out of file handles, you might
want to increase this limit
执行:grep -r MemTotal /proc/meminfo | awk "{printf("%d",$2/10)}",可以看到与file-max是相近的;
This denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on RLIMIT_NOFILE
resource limit.
file-max是内核可分配的最大文件数,nr_open是单个进程可分配的最大文件数,所以在我们使用ulimit或limits.conf来设置时,
如果要超过默认的1048576值时需要先增大nr_open值(sysctl -w fs.nr_open=100000000或者直接写入sysctl.conf文件)。
当然百万级别的单进程最大file-handle打开数应该也够
参考资料:https://www.jianshu.com/p/8fb056e7b9f8
句柄和文件描述符(FD)
https://www.jianshu.com/p/0ff9ff1d108e