写在前面,linux的描述符有进程描述符、文件描述符、内存描述符。首先标题想了很久linux的描述符从哪里说起,看了几份资料后还是决定从进程描述符说起。但是此文章还是重点说的是文件描述符。知识深度有限,如有错误,请指出。

进程描述符:linux为了管理进程,内核必须对每个进程所作的事情进行清楚的描述,例如内核必须知道进程的优先级,它是正在cpu上运行还是因某事而被堵塞?给它分配了什么样的地址空间(内存描述符),可访问哪些文件(文件描述符),进程描述符存放很多信息,如下图:

image.png


files_struct 如下图:

image.png


从上图可得:

task_struct ----->  file_struct(fd)   -----> find opened file list -----> 被打开文件的信息(dentry)  ----->  文件本身信息(inode)  -----> 磁盘


文件描述符fd:

文件描述符是linux内核为了高效管理已被打开的文件所创建的索引,所有的IO操作系统调用都是使用文件描述符。

每打开一个文件都会创建文件描述符,并将文件指针指向这个文件描述符,文件描述符由非负整数表示,系统默认的3个文件描述符是0,1,2,即标准输入、标准输出、标准错误输出。

此时打开一个文件即从3开始,写入到文件描述符表中。每个进程在PCB(Process Control Block)即进程控制块中都保存着一份文件描述符表。

能打开多少文件描述符?理论来说内存有多大就可以打开多少文件描述符,但内核进行管理 一般是内存的10%(系统限制)。


查看系统限制可以创建多少文件描述符:

方法1.
[root@WebA-136 ~]# sysctl -a | grep fs.file-max
fs.file-max = 98622

方法2.
[root@WebA-136 ~]# cat /proc/sys/fs/file-max
98622
[root@WebA-136 ~]#


内核为了不让某个进程消耗掉所有文件资源,会对单个进程最大打开文件个数做限制:

查看用户级别的使用ulimit

[root@WebA-136 ~]# ulimit -n#列出每个进程可以打开的文件数,此值不能超过1024*1024,内核限制,若要超过此值需要重新编译内核。从内核2.6.25可以动态修改此值vim /proc/sys/fs/nr_open
1024
[root@Management-Machine-140 ~]# cat /proc/sys/fs/nr_open
1048576
[root@Management-Machine-140 ~]# ulimit -n 1048577
-bash: ulimit: open files: cannot modify limit: Operation not permitted

[root@Management-Machine-140 ~]# echo '1048577' > /proc/sys/fs/nr_open
[root@Management-Machine-140 ~]# cat /proc/sys/fs/nr_open
1048577
[root@Management-Machine-140 ~]# ulimit -n 1048577

修改系统限制

临时修改
[root@WebA-136 ~]# sysctl -w fs.file-max=400000
fs.file-max = 400000
You have new mail in /var/spool/mail/root
[root@WebA-136 ~]# echo 350000 >/proc/sys/fs/file-max
[root@WebA-136 ~]# sysctl -a | grep fs.file-max
fs.file-max = 350000
[root@WebA-136 ~]#
永久修改
将fs.file-max=400000添加到/etc/sysctl.conf配置文件中。


ulimit命令:限制进程对系统资源的使用情况。常用限制有:

    内核文件大小限制

    进程数据块大小限制

    shell进程创建文件大小限制

    可加锁内存大小限制

    常驻内存集大小限制

    打开文件描述符数量限制

    分配堆栈的最大大小限制

    cpu占用时间限制用户最大可用的进程数限制

    shell进程所能使用的最大虚拟内存限制


常用选项:

    -a  显示当前系统所有的limit资源信息

    -H  设置硬资源限制,一旦设置不能增加

    -S  设置软资源限制,设置后可以增加,但是不能超过硬资源设置

    -c  最大的core文件的大小,以 blocks 为单位

    -f  进程可以创建文件的最大值,以blocks 为单位

    -d  进程最大的数据段的大小,以Kbytes 为单位

    -m  最大内存大小,以Kbytes为单位

    -n  可以打开的最大文件描述符的数量

    -p  管道缓冲区的大小,以Kbytes 为单位

    -s  线程栈大小,以Kbytes为单位

    -u  用户最大可用的进程数

    -v  进程最大可用的虚拟内存,以Kbytes 为单位

    -t  最大CPU占用时间,以秒为单位

    -l  最大可加锁内存大小,以Kbytes 为单位


修改用户级别

临时修改,重启失效
[root@WebA-136 ~]# ulimit -SHn 10240#修改可以打开的文件描述符数量限制
[root@WebA-136 ~]# ulimit -n
10240

永久修改,所有用户都生效。将hard,soft写入文件中,此文件格式是#<domain>用户或@组名或*   <type>限制类型hard soft  <item>限制的资源名称  <value> 值
[root@WebA-136 ~]# vim /etc/security/limits.conf

永久修改,所有用户都生效。在/etc/security/limits.d/90-nproc.conf 中,系统会先读取这个文件,此文件中的项目会覆盖/etc/security/limits.conf中的项目,建议将其一内容注释。

永久修改,修改单一用户,写入用户环境变量中  .bash_profile 写入ulimit -SHn 10240.
[root@Management-Machine-140 ~]# echo "ulimit -SHn 10240" >>/root/.bash_profile
[root@Management-Machine-140 ~]# ulimit -n  #已修改
10240
[root@Management-Machine-140 ~]#

或者在应用程序的启动脚本写入ulimit -n 10240


ulimit -a显示当前用户所有系统限制

[root@Management-Machine-140 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 7802
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 7802
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited
[root@Management-Machine-140 ~]#


ulimit -SHn 修改硬限制、软限制和文件描述符数

[root@Management-Machine-140 ~]# ulimit -SHn 11223
[root@Management-Machine-140 ~]# ulimit -n
11223
[root@Management-Machine-140 ~]# . /root/.bash_profile#我这里已经对当前用户所有进程都设置打开文件描述符数为10240了
[root@Management-Machine-140 ~]# ulimit -n
10240
[root@Management-Machine-140 ~]#


查看用户可以创建的进程数量限制

[root@Management-Machine-140 ~]# ulimit -u
7802
[root@Management-Machine-140 ~]#


查看所有用户创建的进程数量

[root@Management-Machine-140 ~]# ps h -Led -o user | sort | uniq -c | sort -n
      2 dbus
      2 postfix
    193 root


注:ulimit 生效后,若是web服务器。需要重启web服务。