linux文件描述符
所有执行I/O操作的系统调用都以文件描述符,即一个非负整数来指代所打开的文件。文件描述符可以用来表示所有类型的已打开文件。同时,多个文件描述符可以指向同一个打开文件,因为有在不同进程中打开同一个文件的需求。
一、最大文件描述符的查看方法
1、查看系统级别最大文件描述符
[root@localhost ~]# sysctl -a | grep -i file-max --color
fs.file-max = 181927
或者
[root@localhost ~]# cat /proc/sys/fs/file-max
181927
2、查看用户级别最大文件描述符
[dev@localhost ~]$ ulimit -n
1024
二、最大文件描述符的限制
1、系统级别的限制
它是限制所有用户打开文件描述符的总和。一般是系统内存的10%(以KB来计算)左右。
例如我的系统:在没手动调整系统级别最大文件打开数的情况下,内存为1867048KB,系统级别的最大文件打开数为181927,正好为1/10左右。
2、用户级别的限制
ulimit可以查到用户级别的最大文件描述符限制。也就是说每一个用户登录后执行的单个进程占用文件描述符的数量不能超过这个限制。
例如:用develop用户登录之后,启动了一个tomcat进程和一个redis进程,那么tomcat这个进程占用的文件描述符不能超过ulimit的限制,redis这个进程占用的文件描述符也不能超过ulimit的限制。
三、修改最大文件描述符
1、修改系统级别的最大文件描述符
1)临时修改(重启服务器之后失效)
[root@localhost ~]# sysctl -w fs.file-max=6553500
fs.file-max = 6553500
[root@localhost ~]# cat /proc/sys/fs/file-max
6553500
或者
[root@localhost ~]# echo 6553500 > /proc/sys/fs/file-max
[root@localhost ~]# cat /proc/sys/fs/file-max
6553500
2)永久修改
把fs.file-max=6553500添加到/etc/sysctl.conf中,用sysctl -p即可。
2、修改用户级别的最大文件描述符
1)临时修改(只对当前会话起作用)
[root@localhost ~]# ulimit -SHn 65535
[root@localhost ~]# ulimit -n
65535
2)永久修改
修改**/etc/security/limits.conf**
* hard nofile 65535
* soft nofile 65535
soft 指的是当前系统生效的设置值,hard 表明系统中所能设定的最大值,所以soft<=hard,soft的限制不能比hard限制高。
四、查看目前使用的文件描述符
我的系统是CentOS7.3,lsof的版本是4.87。
1、网上的大部分说法
在网上浏览了一圈,一般都是使用lsof这个命令进行查看的,例如:
lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head
首先我们试一下这个命令
[dev@localhost ~]$ lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head
23115 28398
20043 27273
17100 28184
16497 27940
16192 27341
15481 28007
15210 28079
13172 24416
12079 15437
10788 27874
得到的结果的二列是进程的pid,第一列是这个进程占用的文件描述符。
发现这些进程占用的文件描述符是1万多甚至2万多。
得到的结论是使用lsof查看进程占用的文件描述符是不正确的,具体原因如下:
1)
lsof的结果包含了并非以fd形式打开的文件,比如用mmap方式访问文件(FD一栏显示为mem),实际并不占用fd。
其中包括了像.so这样的文件。从结果看.jar文件也是以FD为mem和具体fd编号分别打开了一次。
2)
不同版本的lsof输出结果不同。CentOS 6.6中的lsof(4.82版本)是按PID/file显示的结果。而CentOS7中的lsof(4.87版本)是按PID/TID/file的组合显示的结果,上面的lsof命令显示”打开”了很多文件的进程,只是因为这些进程运行了N个线程,而每个线程都”用到”了M个jar包,并且FD一栏分别为mem和具体fd号都分别显示了一次,就出现了2*N*M(上万条)的文件描述符的结果。
3)
如果用lsof -p ,则不按TID显示,结果数少很多。但仍包含了没有使用fd的文件。
2、正确的查看文件描述符的方法
1)查看整个系统的fd数量
sudo find /proc -print | grep -P '/proc/\d+/fd/'| wc -l
-P是可以让grep使用perl的正则表达式语法。
注意如果使用sudo ls -l /proc/*/fd/* | wc -l,结果是不对的,比上面的命令返回结果少很多。原因是实际执行是会把*扩充成具体的目录作为参数,而这个参数长度有限制。
2)查看某一个进程的fd数量
ls -l /proc/<pid>/fd | wc -l
我在服务器上查看一下pid为15437的进程
[dev@microservice001 ~]$ ls -l /proc/15437/fd | wc -l
80
然后看一下阿里云的进程监控
两个值是完全一样的,证明方法是正确的。
3)查看哪个进程使用的fd最多
sudo find /proc -print | grep -P '/proc/\d+/fd/'| awk -F '/' '{print $3}' | uniq -c | sort -rn | head
参考文章:
https://www.jianshu.com/p/407c2baef92e
https://blog.csdn.net/kumu_linux/article/details/7877770
还没有评论,来说两句吧...