原理

概念区分

  • 内核维护的打开文件表(System Open File Table)

内核维护着一个打开文件表(看作一个数组),当某个进程打开一个文件时,内核会在这个表中添加一条记录,这个记录是一个结构体,包含了如下数据:文件的偏移量(进程操作(比如读)到文件的哪个位置)等等

一个进程可以打开同一个文件多次,那么就会内核的打开文件表中就会相应地增加多个记录。后文中我们把该表的记录叫做文件句柄

  • 文件描述符(File Descriptor)

上面提到内核维护着一个打开文件表,其实进程也在PCB(Process Control Block)中维护着一个文件描述符表(File Descriptor Table)。当进程打开一个文件时,内核会在打开文件表中新增一条记录,同时进程也会在自已的文件描述符表中添加一条记录,该条记录中有一个指针,指向了内核的打开文件表中对应的记录。

一个进程可以打开同一个文件多次,那么就会在FDT中相应地增加多个记录。后文中我们将用打开文件数来表示进程的文件描述符的个数

Linux的参数调优

我们可能经常会遇到too many open files报错,这是因为“进程的打开文件数(文件描述符)过多,超过了进程的上限(一般都是进程的文件描述符超过限制,目前还没遇到文件句柄超出)”。所以,我们需要对进程的打开文件数上限做调整。

用户

如果没有对进程做显示的设置,进程的打开文件数上限会继承该进程所属的用户的打开文件数上限(正确的表述未找到,可以理解为该用户下单个进程的打开文件数上限)。

我们可以通过以下的方法设置用户的打开文件数上限

$ vim /etc/security/limits.conf
...
<user> - nofile 65535
...

我们也可以通过* - nofile 65535来设置所有用户(*代表所有用户)的打开文件数上限。设置好之后我们可以通过命令ulimit -n来查看当前用户的打开文件数上限。

其实,打开文件数上限有分Soft LimitHard Limit。上面的设置方法中第二列为-,表示同时设置Soft LimitHard Limit。当然,我们也可以通过如下方法来设置用户的Soft LimitHard Limit,需要注意的是Soft Limit不能超过Hard Limit

$ vim /etc/security/limits.conf
...
<user> soft nofile 65535
<user> soft nofile 65534
...

命令ulimit -n查看的其实是Soft Limit。可以通过命令ulimit -Sn查看Soft Limit,通过命令ulimit -Hn查看Hard Limit

系统的默认配置中,每个用户的Soft Limit为1024,Hard Limit为2048

Tips: 建议将用户的Soft LimitHard Limit设为一样,且所有用户都设大一些为65535

这样再说一点实用的小技巧,如果想查看其他用户的最大打开文件数,但是却不知道那个用户的密码。那么可以这样做:首先新建文件 ulimit.sh,内容如下

su -c "ulimit -n" <user>

然后为ulimit.sh添加可执行属性,然后执行

sudo ./ulimit.sh

进程

我们设置特定进程的打开文件数上限,但是注意进程的打开文件数不能超过用户的打开文件数

对于systemd管理的进程,我们可以通过下面的方法同时设置Soft LimitHard Limit

[Service]
LimitNOFILE=65535

可以通过cat /proc/<pid>/limits查看进程的打开文件数上限,如下Max open files一行

$ cat /proc/<pid>/limits
Limit                     Soft Limit           Hard Limit           Units     
...
Max open files            1024                 4096                 files     
...

可以通过命令ls -l /proc/<pid>/fd | wc -l统计进程已经打开的文件数(文件描述符数)

Linux下的指标

  • /proc/sys/fs/file-max

$ cat /proc/sys/fs/file-max
3280853

该指标的官方定义为(官方链接待补充)

The value in file-max denotes the maximum number of file handles that the Linux kernel will allocate. When you get a lot of error messages about running out of file handles, you might want to raise this limit. The default value is 10% of RAM in kilobytes. To change it, just write the new number into the file

也就是说file-max指的是内核中文件句柄数的最大值

  • /proc/sys/fs/file-nr

$ cat /proc/sys/fs/file-nr
6496    0    3280853

其中最后一个参数就是file-max的值,第一个表示已经打开的文件句柄数,(第二个参数暂时还未清楚,好像一直为0

  • /proc/<pid>/fd

$ ls /proc/<pid>/fd
0 1 2 4...

该目录下有很多以数字命名的链接文件,这些数字,其实就是进程的文件描述符表中的索引,即数组的索引。所以经常也把文件描述符看成是一个数字。 进程每打开一个文件,文件描述符就会加1。这个目录下看到的文件描述符不一定连续,因为有些文件可能已经关闭了。

  • /proc/<pid>/limits

$ cat /proc/<pid>/limits
Limit                     Soft Limit           Hard Limit           Units     
...
Max open files            1024                 4096                 files     
...

其中有一行叫Max open files,这里的open files其实就是进程的文件描述符的上限。不过注意有分Soft LimitHard Limit,我们可以为进程设置这两个值,但是Soft Limit必须小于等于Hard Limit(设置方法见《Nofile》)。如果没有给进程设置,则会继承该进程所属用户的配置。执行命令ulimit -Sn可以查看用户的Soft Limit,执行命令ulimit -Hn可以查看用户的Hard Limit

实践

接下来,我们写一个程序,打开一个文件一千次,然后查看内核的打开文件数与进程的文件描述符

执行前,我们先看一下内核的打开文件表,有6496个

$ cat /proc/sys/fs/file-nr 
6496    0    3280853

然后运行该程序

$ ./test.py

接着,我们再来查看内核的打开文件表,为7488,约增加了1000个(因为有别的进程会打开或关闭文件)

$ cat /proc/sys/fs/file-nr 
7488    0    3280853

我们查看该进程的id,为13196

$ ps -ef | grep python
docker    13196 106787  0 21:45 pts/3    00:00:00 /usr/bin/python ./test.py

然后查看进程的文件描述符,有1004个

$ ll /proc/13196/fd | wc -l
1004

$ ls /proc/13196/fd
0     12   144  169  193  217  241  266  290  314  339  363  388  411  436  460  485  509  533  558  582  606  630  655  68   703  728  752  777  800  825  85   874  899  922  947  971  996
1     120  145  17   194  218  242  267  291  315  34   364  389  412  437  461  486  51   534  559  583  607  631  656  680  704  729  753  778  801  826  850  875  9    923  948  972  997
10    121  146  170  195  219  243  268  292  316  340  365  39   413  438  462  487  510  535  56   584  608  632  657  681  705  73   754  779  802  827  851  876  90   924  949  973  998
100   122  147  171  196  22   244  269  293  317  341  366  390  414  439  463  488  511  536  560  585  609  633  658  682  706  730  755  78   803  828  852  877  900  925  95   974  999
1000  123  148  172  197  220  245  27   294  318  342  367  391  415  44   464  489  512  537  561  586  61   634  659  683  707  731  756  780  804  829  853  878  901  926  950  975
1001  124  149  173  198  221  246  270  295  319  343  368  392  416  440  465  49   513  538  562  587  610  635  66   684  708  732  757  781  805  83   854  879  902  927  951  976
1002  125  15   174  199  222  247  271  296  32   344  369  393  417  441  466  490  514  539  563  588  611  636  660  685  709  733  758  782  806  830  855  88   903  928  952  977
101   126  150  175  2    223  248  272  297  320  345  37   394  418  442  467  491  515  54   564  589  612  637  661  686  71   734  759  783  807  831  856  880  904  929  953  978
102   127  151  176  20   224  249  273  298  321  346  370  395  419  443  468  492  516  540  565  59   613  638  662  687  710  735  76   784  808  832  857  881  905  93   954  979
103   128  152  177  200  225  25   274  299  322  347  371  396  42   444  469  493  517  541  566  590  614  639  663  688  711  736  760  785  809  833  858  882  906  930  955  98
104   129  153  178  201  226  250  275  3    323  348  372  397  420  445  47   494  518  542  567  591  615  64   664  689  712  737  761  786  81   834  859  883  907  931  956  980
105   13   154  179  202  227  251  276  30   324  349  373  398  421  446  470  495  519  543  568  592  616  640  665  69   713  738  762  787  810  835  86   884  908  932  957  981
106   130  155  18   203  228  252  277  300  325  35   374  399  422  447  471  496  52   544  569  593  617  641  666  690  714  739  763  788  811  836  860  885  909  933  958  982
107   131  156  180  204  229  253  278  301  326  350  375  4    423  448  472  497  520  545  57   594  618  642  667  691  715  74   764  789  812  837  861  886  91   934  959  983
108   132  157  181  205  23   254  279  302  327  351  376  40   424  449  473  498  521  546  570  595  619  643  668  692  716  740  765  79   813  838  862  887  910  935  96   984
109   133  158  182  206  230  255  28   303  328  352  377  400  425  45   474  499  522  547  571  596  62   644  669  693  717  741  766  790  814  839  863  888  911  936  960  985
11    134  159  183  207  231  256  280  304  329  353  378  401  426  450  475  5    523  548  572  597  620  645  67   694  718  742  767  791  815  84   864  889  912  937  961  986
110   135  16   184  208  232  257  281  305  33   354  379  402  427  451  476  50   524  549  573  598  621  646  670  695  719  743  768  792  816  840  865  89   913  938  962  987
111   136  160  185  209  233  258  282  306  330  355  38   403  428  452  477  500  525  55   574  599  622  647  671  696  72   744  769  793  817  841  866  890  914  939  963  988
112   137  161  186  21   234  259  283  307  331  356  380  404  429  453  478  501  526  550  575  6    623  648  672  697  720  745  77   794  818  842  867  891  915  94   964  989
113   138  162  187  210  235  26   284  308  332  357  381  405  43   454  479  502  527  551  576  60   624  649  673  698  721  746  770  795  819  843  868  892  916  940  965  99
114   139  163  188  211  236  260  285  309  333  358  382  406  430  455  48   503  528  552  577  600  625  65   674  699  722  747  771  796  82   844  869  893  917  941  966  990
115   14   164  189  212  237  261  286  31   334  359  383  407  431  456  480  504  529  553  578  601  626  650  675  7    723  748  772  797  820  845  87   894  918  942  967  991
116   140  165  19   213  238  262  287  310  335  36   384  408  432  457  481  505  53   554  579  602  627  651  676  70   724  749  773  798  821  846  870  895  919  943  968  992
117   141  166  190  214  239  263  288  311  336  360  385  409  433  458  482  506  530  555  58   603  628  652  677  700  725  75   774  799  822  847  871  896  92   944  969  993
118   142  167  191  215  24   264  289  312  337  361  386  41   434  459  483  507  531  556  580  604  629  653  678  701  726  750  775  8    823  848  872  897  920  945  97   994
119   143  168  192  216  240  265  29   313  338  362  387  410  435  46   484  508  532  557  581  605  63   654  679  702  727  751  776  80   824  849  873  898  921  946  970  995

其中012是每个进程都有的,代表stdinstdoutstderr,我们来查看3,如下

$ ll /proc/13196/fd/3
lrwx------ 1 docker docker 64 5月  24 21:46 /proc/13196/fd/3 -> /home/docker/peng/fd/afile

Reference

  • https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/5/html/tuning_and_optimizing_red_hat_enterprise_linux_for_oracle_9i_and_10g_databases/chap-oracle_9i_and_10g_tuning_guide-setting_file_handles

  • https://www.ibm.com/support/knowledgecenter/en/ssw_aix_71/com.ibm.aix.genprogc/using_file_descriptors.htm

  • http://www.opstool.com/article/166

  • https://blog.csdn.net/lizhidefengzi/article/details/71481195

Last updated