Linux 文件描述符
最近在复习tcp/ip知识,其中有关的一个问题 "一台服务器做多支持多少个TCP链接" 和Linux下的文件描述符有关,学习一下。
Linux中,一切设备都是文件,对文件的操作都是通过文件描述符来进行的。
文件描述符的定义:
文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。
Linux中有7种文件类型:
文件类型 | 描述 | 符号 |
普通文件 | 最常使用的一类文件,其特点是不包含有文件系统信息的结构信息。这种类型的文件是按照其内部结构又可分为纯文本文件(ASCII)、二进制文件(binary)、数据格式的文件(data)、各种压缩文件。 | REG (-) |
目录文件 | 用于存放文件名以及其相关信息的文件,是内核组织文件系统的基本节点。 | DIR (d) |
块设备 | 块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。 | BLK (b) |
字符设备 | 字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。 | CHR (c) |
套接字 | 这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。 | SOCK(s) |
管道 | 一种很特殊的文件,主要用于不同进程的信息传递。 | FIFO (p) |
链接 | 一种特殊文件,指向一个真实存在的文件链接,类似于Windows下的快捷方式,链接文件的不同,又可分为硬链接和软链接。 | LNK (l) |
最大文件描述符数量
用户级限制: ulimit -n 可以查看结果
[root@jay ~]# ulimit -n
65535
系统级限制: cat /proc/sys/fs/file-max
[root@jay ~]# cat /proc/sys/fs/file-max
363326
临时修改最大数量:
ulimit -n 20000 将最大值改为20000
需要注意的是普通用户首次使用该命令修改最大数量后再次使用ulimit -n只能越改越小,否则报错。假设用户还没使用ulimit -n:
#第一次可以设不大于/etc/security/limits.conf的任意大小
#如果/etc/security/limits.conf没有限制该用户的大小那么第一次可以设置成任意数量
ulimit -n 2000
#报错 bash: ulimit: open files: cannot modify limit: Operation not permitted
ulimit -n 2000
#可以设为更小的
ulimit -n 1998
#设完更小的值之后也改不回2000了
ulimit -n 2000
#报错bash: ulimit: open files: cannot modify limit: Operation not permitted
root用户不受此限制,可以改大或改小。且root每次修改都可以比/etc/security/limits.conf里的内容大。后面内容会讲到修改/etc/security/limits.conf里的值
此法修改大小仅对当前进程生效。重新登陆或另开进程就失效了。
永久修改文件描述符数量:
vi /etc/security/limits.conf,如果有下面两行就修改数值,没有就添加下面两行:
root hard nofile 65536
root soft nofile 65536
上述语句其实只加了root的,如果没有加用户的限制那么用户首次使用ulimit是可以打开任意数量的,可以比root的限制还要大。假定用户是user,向该文件加如下内容:
user hard nofile 2048
user soft nofile 2048
此时user首次使用ulimit修改大小就不能比2048大了。可以理解为系统自动执行一次ulimit -n 2048,因此不能比上次修改的大。
/proc/sys/fs/file-max系统级限制:
虽然名字叫系统级限制,但是它无法限制最大文件描述符设置的值。这个值只是系统根据内存等资源信息计算出的一个建议值。我们查看以下这个值,我这边是1603892,如果在 /etc/security/limits.conf里进行如下修改:
root hard nofile 2000000
root soft nofile 2000000
重新登陆会发现变成200万
常见误区:
综上常见误区有以下几点:
1.虽然普通用户ulimit -n设置只能越来越小,但是root用户不受限。
2.普通用户如果没有在limits.conf配置最大值,虽然默认是1024,但是首次使用ulimit -n可以设置任意值,即便比root配置值还大。
3.设置完limits.conf不用重启,重新登陆该用户就行。不过重启也可以。
4./proc/sys/fs/file-max只是一个建议值,限制不了文件描述符最大数量
回到最上面的问题
TCP四元组可以确定一个连接:
其中源地址和源端口是确定的(服务器通常固定在某个本地端口上监听,等待客户端的连接请求。)
所以连接数量的最大理论值计算公式即为:
对 IPv4,客户端的 IP 数最多为 2
的 32
次方,客户端的端口数最多为 2
的 16
次方,也就是服务端单机最大 TCP 连接数,约为 2
的 48
次方。
会受到以下因素影响:
1、本文所说的文件描述符,每个tcp连接本质上也是一个文件,如果文件描述符别占满了,会有too many open files的报错。
2、内存限制,每个tcp连接都要占用一定的内存,操作系统的内存是有限的,如果内存资源占满后,会发生OOM。