文件描述符

2022/04/03

[转载]Linux 文件描述符

维基百科:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIXLinux这样的操作系统。

转载信息

一、文件描述符概念

Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行 I/O 操作的系统调用都会通过文件描述符。

二、文件描述符、文件、进程间的关系

2.1. 描述:

  • 每个文件描述符会与一个打开的文件相对应
  • 不同的文件描述符也可能指向同一个文件
  • 相同的文件可以被不同的进程打开,也可以在同一个进程被多次打开

2.2. 系统为维护文件描述符,建立了三个表

2.3. 通过这三个表,认识文件描述符

图片描述

  • 在进程 A 中,文件描述符 1 和 30 都指向了同一个打开的文件句柄(#23),这可能是该进程多次对执行打开操作
  • 进程 A 中的文件描述符 2 和进程 B 的文件描述符 2 都指向了同一个打开的文件句柄(#73),这种情况有几种可能
    • 进程 A 和进程 B 可能是父子进程关系
    • 进程 A 和进程 B 打开了同一个文件,且文件描述符相同(低概率事件)
    • A、B 中某个进程通过 UNIX 域套接字将一个打开的文件描述符传递给另一个进程
  • 进程 A 的描述符 0 和进程 B 的描述符 3 分别指向不同的打开文件句柄,但这些句柄均指向 i-node 表的相同条目(#1936),换言之,指向同一个文件。发生这种情况是因为每个进程各自对同一个文件发起了打开请求。同一个进程两次打开同一个文件,也会发生类似情况。

前人的思考,我们的阶梯,这部分参考自网络:链接

三、文件描述符限制

有资源的地方就有战争,“文件描述符”也是一种资源,系统中的每个进程都需要有“文件描述符”才能进行改变世界的宏图霸业。世界需要秩序,于是就有了“文件描述符限制”的规定。

如下表:

- 用户级限制 系统级限制  
查看 ulimit -n sysctl -a grep -i file-max
修改:session内生效 ulimit -SHn 65535 sysctl -w fs.file-max=65535  
修改:永久生效 echo ‘* - nofile 65535’ » /etc/security/limits.conf echo ‘fs.file-max=65535’ » /etc/sysctl.conf && sysctl -p  

注意下永久修改最好手动打开文件进行编辑,避免 echo 输入导致的内容覆盖问题

永久修改用户级限制时有三种设置类型:

  • soft 指的是当前系统生效的设置值
  • hard 指的是系统中所能设定的最大值
  • - 指的是同时设置了 soft 和 hard 的值

命令讲解:

四、检查某个进程的文件描述符相关内容

步骤(以 nginx 为例,注意权限问题,此示例是在本地环境):

# 找到 nginx 的 pid
root@ubuntu:/home/ubuntu# ps -ef|grep nginx
root      172453  172431  2 04:34 ?        00:00:00 nginx: master process nginx -g daemon off;
systemd+  172512  172453  0 04:34 ?        00:00:00 nginx: worker process
systemd+  172513  172453  0 04:34 ?        00:00:00 nginx: worker process
root      172518  132637  0 04:34 pts/0    00:00:00 grep --color=auto nginx

# 查看该进程(172453)的限制
root@ubuntu:/home/ubuntu# cat /proc/172453/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        unlimited            unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             unlimited            unlimited            processes
Max open files            1048576              1048576              files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       15295                15295                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 为 1048576
# 因为服务是 docker 启动,所以在一个全新的 pid namespace,所以会这么大

# 查看该进程占用了多少个文件描述符
root@ubuntu:/home/ubuntu# ls /proc/172453/fd |wc -w
12

五、总结

实际应用过程中,如果出现 Too many open files,可以通过增大进程可用的文件描述符数量来解决,但往往故事不会这样结束,很多时候,并不是因为进程可用的文件描述符过少,而是因为程序 bug,打开了大量的文件连接(web 连接也会占用文件描述符)而没有释放。程序申请的资源在用完后及时释放,才是解决 Too many open files 的根本之道。 有点瑕疵哦。
关于《三、文件描述符限制》,ulimit -SHn 不是重启有效,而是在这个会话内有效,退出会话就失效了。

六、参考

Search

    Table of Contents