Linux 的进程最多可以打开多少文件

目录

Linux 中不管是 Socket 还是管道,几乎所有东西都有一个文件对应,一个进程能打开的文件数是一个很重要的配置。

修改的必要性

ulimit -n 可以查看每个进程能打开的文件的最大数,这个值默认是 1024,这实际上是非常小的,在很多需要大量 Socket 的应用服务器上绝对不够用。

问题

我们能把这个值最大改为多少呢?
我看到很多网上把这个值修改为 65535 修改为这个值的原因是什么,只能这么大吗?

分析

这个问题恐怕只有从系统调用上去分析原因。我们知道 Linux 的内核是 c 语言写的,在 Linux c 编程时对文件的系统调用有 open,close,我们看一下下面
这两个系统调用的定义就会明白了。

man 2 open

OPEN(2)                                                               Linux Programmer's Manual                                                              OPEN(2)

NAME
       open, creat - open and possibly create a file or device

SYNOPSIS
       #include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>

       int open(const char *pathname, int flags);
       int open(const char *pathname, int flags, mode_t mode);

       int creat(const char *pathname, mode_t mode);

man 2 cloes

CLOSE(2)                                                              Linux Programmer's Manual                                                             CLOSE(2)

NAME
       close - close a file descriptor

SYNOPSIS
       #include <unistd.h>

       int close(int fd);

上面两个系统调用很清楚的显示了,在 Linux 里文件的句柄是一个 int 型的,这也就回答了上面我们的第一个问题,就是 ulimit -n 的最大值就是系统
int 型的范围。那问题又来了,Linux 系统 int 型的范围有多大呢?记得谭浩强老师那本 c 语言的书里,int 型好像是 2 的 16 次方,正好 65535。

得到系统 int 型的大小

我们可以使用下面的代码得到系统 int 型的大小

#include <stdio.h>

int main()
{
    printf("int size is %d\n",sizeof(int));
    return 0;
}

我在 64 位的机器上编译,得到的结果是

jimila@CDYJY-JINGML:testc$ ./a.out 
int size is 4
#这里的单位是 Byte,也就是 4×8=32bit
#所以在我这台 64 位的机器上每个进程能打开的文件数是 2 的 32 次方个,远远大于网上常见的 65535,所以我们在优化系统时要注意这个问题

得到进程能使用的文件句柄数

有了上面的了解,我们用下面的程序来验证一下 ulimit -n 的限制是否生效

#include <stdio.h>

//得到每个进程能使用的最大文件数
int main()
{
  int i = 0;
  for(;;i++) {
    if(fopen("test", "w") == NULL) {
      printf("达到最大数:%d\n", i);
      break;
    }
  }
  return 0;
}

验证

jimila@CDYJY-JINGML:$ ulimit -n                                                                                                                                     
1024
jimila@CDYJY-JINGML:$ ./a.out                                                                                                                                       
达到最大数:1021
root@CDYJY-JINGML:# ulimit -n 2048
root@CDYJY-JINGML:# ./a.out 
达到最大数:2045
root@CDYJY-JINGML:# ulimit -n 100000
root@CDYJY-JINGML:# ./a.out                                                                                                             
达到最大数:99997


#可以看到效果吧 ^-^

目录