linux文件描述符

£神魔★判官ぃ 2023-06-04 13:54 10阅读 0赞

所有执行I/O操作的系统调用都以文件描述符,即一个非负整数来指代所打开的文件。文件描述符可以用来表示所有类型的已打开文件。同时,多个文件描述符可以指向同一个打开文件,因为有在不同进程中打开同一个文件的需求。

一、最大文件描述符的查看方法

1、查看系统级别最大文件描述符

  1. [root@localhost ~]# sysctl -a | grep -i file-max --color
  2. fs.file-max = 181927
  3. 或者
  4. [root@localhost ~]# cat /proc/sys/fs/file-max
  5. 181927

2、查看用户级别最大文件描述符

  1. [dev@localhost ~]$ ulimit -n
  2. 1024

二、最大文件描述符的限制

1、系统级别的限制

它是限制所有用户打开文件描述符的总和。一般是系统内存的10%(以KB来计算)左右。

例如我的系统:在没手动调整系统级别最大文件打开数的情况下,内存为1867048KB,系统级别的最大文件打开数为181927,正好为1/10左右。

2、用户级别的限制

ulimit可以查到用户级别的最大文件描述符限制。也就是说每一个用户登录后执行的单个进程占用文件描述符的数量不能超过这个限制。

例如:用develop用户登录之后,启动了一个tomcat进程和一个redis进程,那么tomcat这个进程占用的文件描述符不能超过ulimit的限制,redis这个进程占用的文件描述符也不能超过ulimit的限制。

三、修改最大文件描述符

1、修改系统级别的最大文件描述符

1)临时修改(重启服务器之后失效)
  1. [root@localhost ~]# sysctl -w fs.file-max=6553500
  2. fs.file-max = 6553500
  3. [root@localhost ~]# cat /proc/sys/fs/file-max
  4. 6553500
  5. 或者
  6. [root@localhost ~]# echo 6553500 > /proc/sys/fs/file-max
  7. [root@localhost ~]# cat /proc/sys/fs/file-max
  8. 6553500
2)永久修改

fs.file-max=6553500添加到/etc/sysctl.conf中,用sysctl -p即可。

2、修改用户级别的最大文件描述符

1)临时修改(只对当前会话起作用)
  1. [root@localhost ~]# ulimit -SHn 65535
  2. [root@localhost ~]# ulimit -n
  3. 65535
2)永久修改

修改**/etc/security/limits.conf**

  1. * hard nofile 65535
  2. * soft nofile 65535

soft 指的是当前系统生效的设置值,hard 表明系统中所能设定的最大值,所以soft<=hard,soft的限制不能比hard限制高。

四、查看目前使用的文件描述符

我的系统是CentOS7.3,lsof的版本是4.87。

1、网上的大部分说法

在网上浏览了一圈,一般都是使用lsof这个命令进行查看的,例如:

  1. lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head

首先我们试一下这个命令

  1. [dev@localhost ~]$ lsof | awk '{print $2}' | uniq -c | sort -rnk1 | head
  2. 23115 28398
  3. 20043 27273
  4. 17100 28184
  5. 16497 27940
  6. 16192 27341
  7. 15481 28007
  8. 15210 28079
  9. 13172 24416
  10. 12079 15437
  11. 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数量
  1. sudo find /proc -print | grep -P '/proc/\d+/fd/'| wc -l

-P是可以让grep使用perl的正则表达式语法。

注意如果使用sudo ls -l /proc/*/fd/* | wc -l,结果是不对的,比上面的命令返回结果少很多。原因是实际执行是会把*扩充成具体的目录作为参数,而这个参数长度有限制。

2)查看某一个进程的fd数量
  1. ls -l /proc/<pid>/fd | wc -l

我在服务器上查看一下pid为15437的进程

  1. [dev@microservice001 ~]$ ls -l /proc/15437/fd | wc -l
  2. 80

然后看一下阿里云的进程监控

在这里插入图片描述

两个值是完全一样的,证明方法是正确的。

3)查看哪个进程使用的fd最多
  1. 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

发表评论

表情:
评论列表 (有 0 条评论,10人围观)

还没有评论,来说两句吧...

相关阅读

    相关 linux文件描述符

    所有执行I/O操作的系统调用都以文件描述符,即一个非负整数来指代所打开的文件。文件描述符可以用来表示所有类型的已打开文件。同时,多个文件描述符可以指向同一个打开文件,因为有在不

    相关 linux 描述符,linux描述符

    linux系统每个对像当做文件来处理。这包括输入和输出的过程。linux用文件描述来标识每个文件对象。文件描述符是一个非负整数,可以唯一地标识会话中打开的文件。每个过程一次最多

    相关 Linux 文件描述符

    Linux当中的文件 > Linux内核将一切视为文件,那么Linux中文件是什么呢? 其既可以是事实上的真正的物理文件,也可以是设备,管道,甚至可以是一块内存,

    相关 linux文件描述符

    由前面的[文件][Link 1]的讲解可知,文件描述符就是一个小整数。 0 & 1& 2 任何程序在运行时都会变成进程,C标准库都会默认为其打开三个输入输出流:stdi