linux之文件最大打开数量
谈打开文件数,不得不谈文件句柄
1.什么是文件句柄?
在文件I/O中,要从一个文件读取数据,应用程序首先要调用操作系统函数并传送文件名,并选一个到该文件的路径来打开文件。该函数取回一个顺序号,即文件句柄(file handle),该文件句柄对于打开的文件是唯一的识别依据。要从文件中读取一块数据,应用程序需要调用函数ReadFile,并将文件句柄在内存中的地址和要拷贝的字节数传送给操作系统。
1.1 linux句柄
Linux中所有的事物或资源都是以文件的形式存在,比如消息、共享内存、连接等,句柄可以理解为指向这些文件的指针。
对于这些句柄,Linux是有数量限制的,单个进程默认可以打开的句柄数上限,可以用以下命令来查看:
$ ulimit -a
查看某个进程的句柄数上限,命令是:
$ ulimit -a PID
linux对能够打开的文件句柄的数量做了限制。限制是分为三个级别:
- fs.file-max (系统级别参数):该参数描述了整个系统可以打开的最大文件数量。但是root用户不会受该参数限制(比如:现在整个系统打开的文件描述符数量已达到fs.file-max ,此时root用户仍然可以使用ps、kill等命令或打开其他文件描述符)。
- soft nofile(用户级别参数):限制单个进程上可以打开的最大文件数。只能在Linux上配置一次,不能针对不同用户配置不同的值。
- fs.nr_open(进程级别参数):限制单个进程上可以打开的最大文件数。可以针对不同用户配置不同的值。
这三个参数之间还有耦合关系,所以配置值的时候还需要注意以下三点:
- 如果想加大soft nofile,那么hard nofile参数值也需要一起调整。如果因为hard nofile参数值设置的低,那么soft nofile参数的值设置的再高也没有用,实际生效的值会按照二者最低的来。
- 如果增大了hard nofile,那么fs.nr_open也都需要跟着一起调整(fs.nr_open参数值一定要大于hard nofile参数值)。如果不小心把hard nofile的值设置的比fs.nr_open还大,那么后果比较严重。会导致该用户无法登录,如果设置的是*,那么所有用户都无法登录。
- 如果加大了fs.nr_open,但是是用的echo "xxx" > ../fs/nr_open命令来修改的fs.nr_open的值,那么刚改完可能不会有问题,但是只要机器一重启,那么之前通过echo命令设置的fs.nr_open值便会失效,用户还是无法登录。所以非常不建议使用echo的方式修改内核参数!!!
2.句柄详解
2.1 系统层面
系统级的最大限制
$ cat /proc/sys/fs/file-max
用户层面的修改都是对一个进程打开的文件句柄数量的限制,我们还需要设置系统的总限制才可以。
假如,我们设置进程打开的文件句柄数是1024 ,但是系统总限制才500,所以所有进程最多能打开文件句柄数量500。从这里我们可以看出只设置进程的打开文件句柄的数量是不行的。所以需要修改系统的总限制才可以
系统级修改临时生效方式:
echo 655350 > /proc/sys/fs/file-max
系统级修改永久生效方式:
vi /etc/sysctl.conf
fs.file-max=1100000 #系统允许打开最大文件数
fs.nr_open=1100000 #进程允许打开最大文件数,这里注意nr_open要比nofile大,否则会出现登录不上
sysctl -p
查看是否生效,如果不行,reboot即可。
2.2 用户层面
用户级的最大限制
$ ulimit -n
用户级修改临时生效方法
重启后失效
ulimit -SHn 10000
ulimit 命令分软限制和硬限制,加-H就是硬限制,加-S就是软限制。默认显示的是软限制,如果运行ulimit 命令修改时没有加上-H或-S,就是两个参数一起改变。硬限制就是实际的限制,而软限制是警告限制,它只会给出警告
用户级修改永久有效方式
vi /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
*表示所用的用户,但有的系统不认, 需要具体的用户名, 比如:
root soft nofile 65535
root hard nofile 65535
重新登录验证,或者reboot后验证。
2.3 进程层面
进程的最大打开文件数和当前打开文件数
$ cat /proc/[pid]/limits 显示当前进程的资源限制
$ cat /proc/[pid]/fd 是一个目录,包含进程打开文件的情况
$ cat /proc/[pid]/task 查看某个进程的线程的详细信息