Linux 最大文件描述符数
最大文件描述符数量
文件描述符是服务器程序的宝贵资源,几乎所有系统调用都是和文件描述符打交道。而系统分配给进程的文件描述符数量有限,因此需要及时关闭那些不用的文件描述符。
Linux对应用程序能打开的最大文件描述符数量,有2个层次限制:用户级限制,系统级限制。
1)用户级限制,是指目标用户运行的所有进程总能打开的文件描述符数量;
2)系统级限制,是指所有用户总共能打开的文件描述符数量。
如何查看用户级文件描述符数限制?
可以使用ulimit命令查看
$ ulimit -n
1024
也可以通过ulimit命令设置用户级文件描述符数限制为max-file-number,不过这种修改是临时性的。
$ ulimit -SHn max-file-number
例如,max-file-number设置为2048
$ ulimit -SHn 2048
$ ulimit -n
2048
如果想要永久修改用户级文件描述符限制,可以在/etc/security/limits.conf文件中加入以下两项:
hard nofile max-file-number
soft nofile max-file-number
第一行是系统的硬限制,第二行是软限制。
如何修改系统级文件描述符数限制?
可以使用sysctl命令修改,不过也是临时性的
$ sysctl -w fs.file-max=max-file-number
如果要永久性修改系统级文件描述符数量限制,则需要在/etc/sysctl.conf 文件中添加这一项:
fs.file-max=max-file-number
然后,执行$ sysctl -p 命令,使更改生效。
如何在C程序中,获取用户级文件描述符数限制?
有两种方式:
1)sysconf 获取 _SC_OPEN_MAX;
2)getrlimit 获取 RLIMIT_NOFILE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <errno.h>
int main()
{
// 方式一: sysconf 获取 _SC_OPEN_MAX
long openMax = sysconf(_SC_OPEN_MAX);
if (openMax == -1) {
perror("sysconf OPEN_MAX error");
return -1;
}
printf("openMax = %ld\n", openMax);
// 方式二: getrlimit 获取 RLIMIT_NOFILE
struct rlimit limit;
if (getrlimit(RLIMIT_NOFILE, &limit) == -1) {
perror("getrlimit RLIMIT_NOFILE error");
return -1;
}
printf("soft limit = %ld, hard limit = %ld\n", limit.rlim_cur, limit.rlim_max);
return 0;
}
运行结果:
$ ./file_max_test
openMax = 1024
soft limit = 1024, hard limit = 4096
相对的,设置用户级文件描述符数限制,可以用setrlimit。注意,
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <errno.h>
int printOpenMax()
{
// 方式一: sysconf 获取 _SC_OPEN_MAX
long openMax = sysconf(_SC_OPEN_MAX);
if (openMax == -1) {
perror("sysconf OPEN_MAX error");
return -1;
}
printf("openMax = %ld\n", openMax);
// 方式二: getrlimit 获取 RLIMIT_NOFILE
struct rlimit limit;
if (getrlimit(RLIMIT_NOFILE, &limit) == -1) {
perror("getrlimit RLIMIT_NOFILE error");
return -1;
}
printf("soft limit = %ld, hard limit = %ld\n", limit.rlim_cur, limit.rlim_max);
return 0;
}
int main()
{
printOpenMax();
// setrlimit 修改系统限制RLIMIT_NOFILE (用户级文件描述符数限制)
struct rlimit limit;
limit.rlim_cur = 2048;
limit.rlim_max = 4096; // 注意不要大于 前面已经读取出来的rlim_max (4096)
int ret = setrlimit(RLIMIT_NOFILE, &limit);
if (ret == -1) {
perror("setrlimit error");
return -1;
}
printOpenMax();
return 0;
}
如何查找文件(描述符)资源泄漏?
如果常驻进程(不会立即关闭的进程),由于忘记关闭文件,如何快速找到原因?
比如下面的程序:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int cnt = 0;
while (1) {
char name[64];
snprintf(name, sizeof(name), "%d.txt", cnt);
int fd = creat(name, 0644);
sleep(10);
++cnt;
}
return 0;
}
可以使用lsof工具,查看文件描述符相关信息。如:
$ ./open_file_test & # 后台运行上面的程序
[1] 24094
$ lsof -p 24094 # 显示指定进程(pid = 24094)打开的所有文件描述符
$ lsof -p 24094
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
open_test 24094 martin cwd DIR 8,1 4096 1728707 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin
open_test 24094 martin rtd DIR 8,1 4096 2 /
open_test 24094 martin txt REG 8,1 10417 1724410 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/open_test
open_test 24094 martin mem REG 8,1 1857312 2101633 /lib/x86_64-linux-gnu/libc-2.19.so
open_test 24094 martin mem REG 8,1 149120 2101617 /lib/x86_64-linux-gnu/ld-2.19.so
open_test 24094 martin 0u CHR 136,15 0t0 18 /dev/pts/15
open_test 24094 martin 1u CHR 136,15 0t0 18 /dev/pts/15
open_test 24094 martin 2u CHR 136,15 0t0 18 /dev/pts/15
open_test 24094 martin 3w REG 8,1 0 1724300 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/0.txt
open_test 24094 martin 4w REG 8,1 0 1724324 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/1.txt
open_test 24094 martin 5w REG 8,1 0 1724332 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/2.txt
open_test 24094 martin 6w REG 8,1 0 1724333 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/3.txt
open_test 24094 martin 7w REG 8,1 0 1724334 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/4.txt
open_test 24094 martin 8w REG 8,1 0 1724337 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/5.txt
open_test 24094 martin 9w REG 8,1 0 1724338 /home/martin/workspace/CLionProjects/c++/eftp/cmake-build-debug/bin/6.txt
可以清楚看到进程open_file_test (pid = 24094)打开了哪些文件,而没有被关闭。
参考
《Linux高性能服务器编程》
https://blog.csdn.net/CMbug/article/details/48313107