Linux系统IO-文件描述符详解

时间:2024-09-29 10:53:51

1.什么是文件描述符?

在 类Unix操作系统 上,普遍将操作系统上的资源抽象成文件这一概念,诸如硬件设备、普通文件、scoket套接字、可移动存储等介质都被抽象为文件。那么,「文件描述符」 和 「文件」 之前有什么关系呢?

首先,来看看 「文件描述符」是怎么出现的?

在 Linux 操作系统中,当一个应用程序或进程操作系统资源时,首先会触发文件调用事件,通过应用程序或进程发送一个调用文件的信号给操作系统内核,内核会在 打开文件表 中增加一条记录,同时将 打开文件表中新增的记录 返回给应用程序或进程,而应用程序或进程接收到来自内核返回的信息,称为 文件描述符(file desrciption)

实际上,通过 内核 返回的文件描述符正是 打开文件表 中该文件的索引记录,是一个非负整数。文件描述符 通常从 3 开始记录。

在Linux操作系统上,每个进程都有三个标准的 「POSIX」文件描述符,对应三个标准流,按照索引以 0 开始,分别是 Standard Input(标准输入)Standard Output(标准输出)Standard Error(标准错误)

2.文件描述符在操作系统中的应用

文件描述符 是操作系统上非常重要的资源,所有涉及到 I/O 的操作都与 文件描述符相关。但操作系统上自身的资源本就有限,对应的 文件描述符 自然不可能无穷无尽。因此,了解和设置操作系统中的 文件描述符 对于系统健康有着不可忽视的作用。

查看最大可使用的文件描述符数量

[root@server ~]# ulimit -n 65536

你以为 ulimit -n 查看到的是整个系统最大可用的文件描述符数量吗?答案是不是的, Linux 操作系统是 多用户操作系统,为了避免系统资源被单一用户耗尽,系统又为每个用户做了限制,限制每个用户可以使用多少资源。另外,文件描述符的数量和操作系统的内存资源相关(为什么会和内存有关呢,因为打开一个文件要消耗内存资源呢)。

那么,上面的 ulimit -n 你现在可以知道了,对于 root 用户来说,最大可用的文件描述符就是 65536。

若要查看操作系统上最大可使用的文件描述符数量,可通过 sysctl -a 查看

[root@server ~]# sysctl -a | grep -i file-max fs.file-max = 6438631

修改文件描述符数量

当操作系统本身的内存资源很小或者内存足够用的情况下,需要动态调整系统分配的文件描述符的数量,可通过命令进行调整。

(用户级)调整可使用的最大数量的文件描述符

[root@server ~]# ulimit -SHn 2048 [root@server ~]# ulimit -n 2048

说明:通过 ulimit 修改仅针对当前用户的当前终端,倘若使用另一终端进行登录,会发现 fs 还是设置前的值。退出当前终端后重新建立 ssh 连接,结果一样。

(系统级)调整可使用的最大数量的文件描述符

# 修改 /etc/sysctl.conf 文件,增加一行配置 fs.file-max=97178

说明:通过配置文件修改后,需要使用 sysctl -p 使其生效;修改后的配置永久生效。

3.查看某个进程使用的文件描述符

操作系统中应用程序或进程的调度总是在和文件打交道,对于一个活动着的进程,同样可以通过进程看到对应的 文件描述符 的信息。

以 oracle 数据库为例,查看 oracle 中的 pmon 进程打开了多少文件描述符

查询 pmon 进程的进程id

[root@server ~]# ps -ef | grep ora_pmon

root 53876 123535 0 14:38 pts/0 00:00:00

grep --color=auto ora_pmon oracle 253184 1 0 Nov03 ? 00:00:10 ora_pmon_rac2

可以看到 oracle pmon进程对应的进程id为 253184

通过进程id查看进程最大可调用的文件描述符数量

[root@server ~]# cat /proc/253184/limits

Limit Soft Limit Hard Limit Units

Max cpu time unlimited unlimited seconds

Max file size unlimited unlimited bytes

Max data size unlimited unlimited bytes

Max stack size 33554432 33554432 bytes

Max core file size unlimited unlimited bytes

Max resident set unlimited unlimited bytes

Max processes 65536 65536 processes

Max open files 65536 65536 files

Max locked memory unlimited unlimited bytes

Max address space unlimited unlimited bytes

Max file locks unlimited unlimited locks

Max pending signals 511917 511917 signals

Max msgqueue size 819200 819200 bytes

Max nice priority 0 0

Max realtime priority 0 0

Max realtime timeout unlimited unlimited us

如上第10行,Max open files 即为 oracle pmon进程可调度的最大文件描述符数量,为 65536 个。

查看进程已经使用的文件描述符

[root@server ~]# ls /proc/253184/fd/

0 10 12 14 16 18 2 21 23 25 27 29 30 32 34 36 38 4 41 43 45 5 59 60 62 64 66 68 7 71 73 75 77 79 80 82 84 9 1 11 13 15 17 19 20 22 24 26 28 3 31 33 35 37 39 40 42 44 46 53 6 61 63 65 67 69 70 72 74 76 78 8 81 83 85

如上所有的数字编号为 进程 已经打开的 文件描述符的索引。这其中,有几个特殊的文件描述符:

0: 为(Standard Input) 标准输入,在该进程中,标准输入指向 /dev/null

1: 为(Standard Output) 标准输出,在该进程中,标准输入指向 /dev/null

2: 为(Standard Error) 标准错误,在该进程中,标准输入指向 /dev/null

另外,可通过 ls -lh/proc/253184/fd/ 查看每个文件描述符相关的进程调用。

#ls -lh /proc/253184/fd/

total 0 lr-x------ 1 oracle asmadmin 64 Nov 3 15:01 0 -> /dev/null

l-wx------ 1 oracle asmadmin 64 Nov 3 15:01 1 -> /dev/null

l-wx------ 1 oracle asmadmin 64 Nov 3 15:01 2 -> /dev/null

lr-x------ 1 oracle asmadmin 64 Nov 3 15:01 3 -> /dev/null /opt/***/***/***/lib/libocrb19.so

lrwx------ 1 oracle asmadmin 64 Nov 3 15:01 4 -> anon_inode:[eventpoll]

lr-x------ 1 oracle asmadmin 64 Nov 3 15:01 41 -> /usr/lib64/ld-2.17.so ...

lrwx------ 1 oracle asmadmin 64 Nov 3 15:01 59 -> socket:[1898299425]