[转载]Linux 文件描述符
维基百科:文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。
转载信息
- 作者:waterandair
- 发表时间:2017-07-03
- 原始链接:文件描述符(File Descriptor)简介
一、文件描述符概念
Linux 系统中,把一切都看做是文件,当进程打开现有文件或创建新文件时,内核向进程返回一个文件描述符,文件描述符就是内核为了高效管理已被打开的文件所创建的索引,用来指向被打开的文件,所有执行 I/O 操作的系统调用都会通过文件描述符。
二、文件描述符、文件、进程间的关系
2.1. 描述:
- 每个文件描述符会与一个打开的文件相对应
- 不同的文件描述符也可能指向同一个文件
- 相同的文件可以被不同的进程打开,也可以在同一个进程被多次打开
2.2. 系统为维护文件描述符,建立了三个表
- 进程级的文件描述符表
- 系统级的文件描述符表
- 文件系统的 i-node 表 (转到:阮一峰——理解inode)
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 不是重启有效,而是在这个会话内有效,退出会话就失效了。