Linux文件描述符和限制
文件描述符是什么? 与文件句柄的区别是什么?
文件描述符是linux/unix操作系统特有的概念。 相当于windows系统的文件句柄。 一个意思不同的称呼。
在Linux系统上,每次进程打开文件时,都会分配一个唯一的整数文件描述符来标识文件。 标准c包含三个缺省情况下打开的进程:标准输入、标准输出和标准错误,它们分别由文件结构stdin、stout和sterr的指针表示。 这三种结构分别对应于三个文件描述符0、1和2。
文件描述符是一个简单的整数,用于标识进程打开的每个文件和套接字。 第一个打开的文件是0,第二个是1。 在linux操作系统中,通常对每个进程l可以打开的文件数量有限制。
linux系统的文件描述符限制
linux系统的文件描述符限制有两个系统级别
在cat /proc/sys/fs/file-max中,缺省值由系统根据内存大小自动设置,通常为内存大小(KB )的10%,但在外壳下,这种情况类似
2
3
4
5 root @ Ubuntu :~# cat/proc/sys/fs/file-max
188273
root @ Ubuntu :~# grep-rmem total/proc/meminfo|awk ' { printf },$2/10 '
183976
用户级别:默认值为1024,以ulimit -n显示1
2root@ubuntu:~# ulimit -n
1024
为什么要限制打开的文件描述符
资源问题:每个打开的文件都需要占用和管理内存,但内存有限。
安全问题:否则,如果不友好的人启动进程无限地创建或打开新文件,服务器将崩溃。
因此,限制文件描述符的数量对linux系统的稳定性非常重要。
配置文件
限制资源使用的配置文件/etc/security/limits.conf
/etc/security/limits.d/目录
/etc/security/limits.d/背面配置涵盖/etc/security/limits.conf的配置
可以限制的资源类型是要创建的内核文件的大小
过程数据块的大小
外壳流程创建文件的大小
内存锁的大小
常驻内存集的大小
要打开的文件描述符数
分配堆栈的最大大小
CPU时间
每个用户的最大线程数
外壳进程可使用的最大虚拟内存
设置同时支持硬资源和软资源的限制
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 root @ Ubuntu :~# cat/etc/security/limits.conf
#
#
#* soft core 0
# root硬件核心100000
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#ftp - chroot /ftp
#@student - maxlogins 4
* soft nofile 51200
*硬盘文件51200
#End of file
第一列表示用户和组。 以@开头
第二列表示是软限制还是硬限制
第三列显示了有限的资源类型
第四列表示限制的最大值
hard和soft的差异: soft是警告值,hard是真正意义的阈值,超过时会发生错误,通常设定为相同的值。
core是内核文件,nofile是文件描述符,noproc是进程,通常只限制文件描述符数和进程数就足够了
查看系统级别
1
2 root @ Ubuntu :~# cat/proc/sys/fs/file-max
183976
设置
暂时的
1root@ubuntu:~# echo 1
000000 > /proc/sys/fs/file-max永久性
在/etc/sysctl.conf中设置,应该设什么值是最佳实践?比如8G的内存,设为8192/2 * 256 = 5242881fs.file-max = 1000000
用户级别
查看,-n默认查看的是soft limit,这个值是从/etc/security/limits.conf文件的* soft nofile 655350来的
1
2root@ubuntu:~# ulimit -n
170000
查看hard limit
1
2root@ubuntu:~# ulimit -Hn
170000
设置
临时性
通过ulimit -Sn设置最soft limit,注意soft limit必须小于hard limit1ulimit -Sn 160000
通过ulimit -Hn设置最Hard limit1ulimit -Hn 160000
同时设置soft limit和hard limit。对于非root用户只能设置比原来小的hard limit1ulimit -n 180000
永久性
root权限下,在/etc/security/limits.conf中添加如下两行,*表示所有用户,重启生效1
2* soft nofile 102400
* hard nofile 104800
注意:设置nofile的hard limit还有一点要注意的就是hard limit不能大于/proc/sys/fs/nr_open,假如hard limit大于nr_open,注销后将无法正常登录。
当前打开的文件描述符
查看系统当前打开的文件描述符数量
其中第一个数表示当前系统分配后已使用的文件描述符数,第二个数表示分配后未使用的(内核2.6版本中这个值总是为0,这并不是一个错误,它意味着已经分配的文件描述符总会被使用),第三个数等于最大值file-max。
1
2root@ubuntu:~# cat /proc/sys/fs/file-nr
2176 0 2048000
查看某个进程打开的文件描述符数量1
2root@ubuntu:~# ls /proc/35961/fd | wc -l
20
看下哪些进程占用的文件描述符比较多,排下序1
2
3
4
5
6
7
8root@ubuntu:~# sudo find /proc -print | grep -P '/proc/d+/fd/'| awk -F '/' '{print $3}' | uniq -c | sort -rn
Count PID
129 1994
124 1993
122 1995
119 1992
118 23747
69 5504
错误的查看方法
使用lsof查看打开文件数是错误的sof的结果包含了并非以fd形式打开的文件,比如用mmap方式访问文件(FD一栏显示为mem),实际并不占用fd。
其中包括了像.so这样的文件。从结果看.jar文件也是以FD为mem和具体fd编号分别打开了一次。
CentOS 7的lsof(我这里lsof -v的版本号是4.87)是按PID/TID/file的组合对应一行,不是一行一个fd。同一个进程如果多个线程访问同一个文件通常只需要打开一次、占用一个fd,但在lsof中就显示多行。
如果用lsof -p ,则不按TID显示,结果数少很多。但仍包含了没有使用fd的文件。
正确的查看方法
查看/proc/中文件准确的查看fd使用总数的命令1cat /proc/sys/fs/file-nr
或者(结果多的时候运行需要一段时间)1sudo find /proc -print | grep -P '/proc/d+/fd/'| wc -l
查看具体一个进程号的fd数量1ls -l /proc//fd | wc -l
查看哪个进程使用的fd最多,并排序1sudo find /proc -print | grep -P '/proc/d+/fd/'| awk -F '/' '{print $3}' | uniq -c | sort -rn
但还要注意上面的命令返回的是系统的fd使用情况,而ulimit的配置是针对单用户的,两者是有区别的