linux文件描述符

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux文件描述符相关的知识,希望对你有一定的参考价值。

参考技术A Linux 下,一切皆文件

在Linux操作系统中,可以将一切都看作是文件,包括普通文件,目录文件,字符设备文件(如键盘,鼠标…),块设备文件(如硬盘,光驱…),套接字等等,所有一切均抽象成文件,提供了统一的接口,方便应用程序调用。

既然在Linux操作系统中,你将一切都抽象为了文件,那么对于一个打开的文件,我应用程序怎么对应上呢?

文件描述符应运而生。

文件描述符:File descriptor,简称fd,当应用程序请求内核打开/新建一个文件时,内核会返回一个文件描述符用于对应这个打开/新建的文件,其fd本质上就是一个 非负整数 。实际上,它是一个索引值,指向 内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。 在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。

操作系统的核心叫内核,是一个独立的软件。

操作系统为每一个进程维护了一个文件描述符表,该表的索引值都从从0开始的,所以在不同的进程中可以看到相同的文件描述符,这种情况下相同的文件描述符可能指向同一个文件,也可能指向不同的文件,具体情况需要具体分析,下面用一张简图就可以很容易的明白了。

通过上图可以看到,当不同进程中出现相同的文件描述符时,可能实际对应的文件并不是同一个,相反不同进程中不同的文件描述符也可可能对应同一个文件。

当一个应用程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。POSIX标准要求每次打开文件时(含socket)必须使用当前进程中最小可用的文件描述符号。

文件描述符是一个重要的系统资源,理论上系统内存多大就应该可以打开多少个文件描述符,但是实际情况是,内核会有系统级限制,以及用户级限制(不让某一个应用程序进程消耗掉所有的文件资源,可以使用ulimit -n 查看)。

进程 + 文件描述符ID确认,因为内核为每个进程都有一份其所属的文件描述符表。

所以linux下两个进程返回的文件描述符是不一样的

多个进程之间的fd:

应用程序进程拿到的 文件描述符ID 对应 进程文件描述符表 的索引,通过索引拿到 文件指针 ,指向系统级文件描述符表的 文件偏移量 ,再通过文件偏移量找到 inode指针 ,最终对应到真实的文件。

[转帖]linux文件描述符文件/etc/security/limits.conf

linux文件描述符文件/etc/security/limits.conf

文件描述符是什么?和文件句柄有啥区别?

文件描述符是linux/unix操作系统中特有的概念。相当于windows系统中的文件句柄。一个意思不同叫法。

Linux系统中, 每当进程打开一个文件时,系统就为其分配一个唯一的整型文件描述符,用来标识这个文件。标准C中每个进程默认打开的有三个文件,标准输入,标准输出,标准错误,分别用一个FILE结构的指针来表示,即stdin,stout,sterr,这三个结构分别对应着三个文件描述符0,1,2。

文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。第一个打开的文件是0,第二个是1,依此类推。linux 操作系统通常对每个进程l能打开的文件数量有一个限制。

linux系统对文件描述符的限制有两个级别

系统级别:使用cat /proc/sys/fs/file-max查看,默认值是根据内存大小,系统自动设置的,一般为内存大小(KB)的10%,shell下可以这样计算grep -r MemTotal /proc/meminfo | awk ‘printf("%d",$2/10)‘(可能有各种其他原因导致file-max没有设置为内存的10%)

用户级别:默认是1024,使用ulimit -n查看

为什么要限制打开的文件描述符?

原因1 – 资源问题:每个打开的文件都需要消耗内存来管理,而内存是有限的。

原因2 – 安全问题:如果不限制的话,有不怀好心的人启动一个进程来无限的创建和打开新的文件,会让服务器崩溃。

所以限制文件描述符的数量对于linux系统的稳定性是非常重要的。

配置文件

限制资源使用的配置文件是 /etc/security/limits.conf,和/etc/security/limits.d/目录,/etc/security/limits.d/里面配置会覆盖/etc/security/limits.conf的配置

可以限制的资源类型如下:

所创建的内核文件的大小、进程数据块的大小、Shell 进程创建文件的大小、内存锁住的大小、常驻内存集的大小、打开文件描述符的数量、分配堆栈的最大大小、CPU 时间、单个用户的最大线程数、Shell 进程所能使用的最大虚拟内存。同时,它支持硬资源和软资源的限制。

  • 第一列表示用户和组(@开头)。第二列表示软限制还是硬限制,第三列表示限制的资源类型,第四列表示限制的最大值

  • hard和soft的区别: soft是一个警告值,而hard则是一个真正意义的阀值,超过就会报错,一般情况下都是设为同一个值。

  • core是内核文件,nofile是文件描述符,noproc是进程,一般情况下只限制文件描述符数和进程数就够了

#<domain>      <type>  <item>         <value>
#

#*               soft    core            0
#root            hard    core            100000
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#ftp             -       chroot          /ftp
#@student        -       maxlogins       4

# End of file

-----------分割线,上面是配置文件的模板,下面是自己添加的------------------------

*                 soft     nofile         655350      #表示任何一个用户可以打开的最大的文件描述符数量
*                 hard    nofile         655350

*                 soft    nproc          655350      #表示任何一个用户可以打开的最大的进程数
*                hard    nproc          655350


@student        hard    nofile          65535       #student组中的任何人最多能打开文件描述符数量是65535,并且会在打开65000个时发出警告
@student        soft    nofile          65000

@student        hard    nproc           50            #student组中的任何人不能拥有超过50个进程,并且会在拥有30个进程时发出警告
@student        soft    nproc           30

 

系统级别

1、查看

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

2、设置

临时性

$ echo 1000000 > /proc/sys/fs/file-max

永久性

在/etc/sysctl.conf中设置,应该设什么值是最佳实践?比如8G的内存,设为8192/2 * 256 = 524288

fs.file-max = 1000000 

用户级别

1、查看,-n默认查看的是soft limit,这个值是从/etc/security/limits.conf文件的* soft nofile 655350来的

$ ulimit -n
170000

查看hard limit

$ ulimit -Hn
170000

2、设置

临时性:

通过ulimit -Sn设置最soft limit,注意soft limit必须小于hard limit

$ ulimit -Sn 160000

通过ulimit -Hn设置最Hard limit

$ ulimit -Hn 160000

同时设置soft limit和hard limit。对于非root用户只能设置比原来小的hard limit。

ulimit -n 180000

 

永久性:

root权限下,在/etc/security/limits.conf中添加如下两行,*表示所有用户,重启生效

* soft nofile 102400

* hard nofile 104800

 

注意:设置nofile的hard limit还有一点要注意的就是hard limit不能大于/proc/sys/fs/nr_open,假如hard limit大于nr_open,注销后将无法正常登录。

 

查看系统当前打开的文件描述符数量

其中第一个数表示当前系统分配后已使用的文件描述符数,第二个数表示分配后未使用的(内核2.6版本中这个值总是为0,这并不是一个错误,它意味着已经分配的文件描述符总会被使用),第三个数等于最大值file-max。

$ sudo cat /proc/sys/fs/file-nr 
2176    0    2048000

 

查看某个进程打开的文件描述符数量

$ lsof -p 20262 |wc -l
5

 

看下哪些进程占用的文件描述符比较多,排下序

[[email protected]] ~$ lsof -n |awk print $10|sort |uniq -c |sort -nr|head -10
   2367 
    838 socket
    703 /dev/null
    658 pipe
    599 [eventpoll]
    533 [eventfd]
    495 /
    183 (ESTABLISHED)
    178 protocol:
    175 /usr/bin/containerd-shim

 

https://blog.csdn.net/cywosp/article/details/38965239
https://www.cnblogs.com/fsw-blog/p/4543914.html
http://www.bidutools.com/?p=914
https://jameswxx.iteye.com/blog/2096461

以上是关于linux文件描述符的主要内容,如果未能解决你的问题,请参考以下文章

Linux 文件描述符

【fd】Linux文件描述符

Shell自定义输入输出文件描述符

Linux中的文件描述符与打开文件之间的关系

linux系统中用户文件描述符0表示

Linux中的文件描述符