File Descriptor and Open File
春節前一週個週末,因為一個服務系統異常,讓我又重新 review 關於 File Descriptor
(以下簡稱 FD) 的概念。上次整理 已經是兩年前的,再重新讀了相關資料,整理以下部分:
- FD 基本概念
- 設定層級,以及各個層級的詳細設定方法和關係
- FD 應用場景與問題
File Descriptor
依照 wiki 的描述,File Descriptor
是 Unix-like OS 裡的抽象處理標記 (indicator, handle),一般用來處理檔案或者輸入輸出 (input / output) 的資源,像是 pipe
或者 network socket
。
FD 源自於 POSIX, 他是非負數的 integer
, 通常是 C 語言的 int
type. 每一個 Unix process 預期有三個 POSIX FD:
stdin
: value 0stdout
: value 1stderr
: value 2
在 terminal 每一個指令在執行的時候,都會產生 process 以及對應的 PID
。這些 process 執行的時候,他們相關的資料,在 Linux 會存放在 /proc/PID/
底下。
底下是取的 PID 相關資訊的方法:
1 | ## 取的當前的 PID |
透過 /proc/PID
裡的資訊,可以知道很多 process 的資訊,通常找問題,或者資源不足時,可以先從這裡下手。
FD 的設定層級範圍
分成 Shell Session
、User Level
、System Level
三個層級:
Shell Session
: 調整當前的 FD 數,指令為ulimit
- 一般使用者只能減小不能變大
- root 則不受限制
User Level
: 指定特定使用者的預設值,設定檔在/etc/security/limits.conf
System Level
: 系統開機時OpenFiles
的設定值- 這是軟設定,可以隨時調整、或者小於 User Level / Shell Session
- 設定值存在
/proc/sys/fs/file-max
底下分別說明三個的差異。
Shell Session: ulimit
ulimit 是使用者登入時 shell session 的 limit,可以查詢或者修改當前的 session 的各種 limit,包含 open file descriptors, amount of cpu time, number of processes, … 等一堆。manual 的第一句描述如下:
ulimit provides control over the resources available to the shell and to processes started by it, on systems that allow such control.
注意,不是限制單一 process
的數量,而是一個 shell 或者特定 user 的身份。
針對 OpenFiles
常用的參數就是 Soft and Hard limit, 底下顯示 open file 的狀況:
1 | # 顯示最大 `Hard Limit` |
臨時調整 open file limit:
1 | ulimit -n 10000 |
但是這個設定,離開 Shell Session 就無效了。
底下做了一個實驗,流程大概是:
- 取得現在 bash 的
PID
,不更改 Number of Open Files (NOF) - fork 第二層 bash process,更改 NOF
- fork 第三層 bash process,確認 NOF
- 離開第三層,確認 NOF
- 離開第二層,確認 NOF
1 | ## 取的當前 PID |
這個實驗得到幾個結論:
- ulimit 的設定是 session 的,離開就會失效
- forked process 會使用 ulimit 的設定,取代
limits.conf
的值
User Level: limits.conf
這是 PAM (Pluggable Authentication Modules) 的設定,主要可以針對使用者、群組,然後設定不同資源的限制。底下是 man limits.conf
的描述:
The
pam_limits.so
module applies ulimit limits, nice priority and number of simultaneous login sessions limit to user login sessions. This description of the configuration file syntax applies to the/etc/security/limits.conf
file and*.conf
files in the/etc/security/limits.d
directory.
limits.conf
的設定位置: /etc/security/limits.conf
,內容主要有底下四個欄位:
[domain] [type] [item] [value]
- domain: a username, group, wildcard
- type:
hard
: for enforcing hard resource limits. These limits are set by the superuser and enforced by the Kernel. The user cannot raise his requirement of system resources above such values.soft
: for enforcing soft resource limits. These limits are ones that the user can move up or down within the permitted range by any pre-existing hard limits. The values specified with this token can be thought of as default values, for normal system usage.-
: for enforcing both soft and hard resource limits together.
- item:
nofile
: number of filenproc
: number of processesfsize
: maximum filesize (KB)- 很多 … 略
- value: -1, unlimited or infinity
- 預設是
1024
- 預設是
修改完 /etc/security/limits.conf
,不用重開機,只要重新登入就會生效。
使用者登入時,如果 limits.conf
有設定,則使用,沒有設定,就是預設 1024。需要臨時調整則使用 ulimit -n [num]
System Level: file-max
man proc
找到 file-max
的說明如下:
This file defines a system-wide limit on the number of open files for all processes. System calls that fail when encountering this limit fail with the error
ENFILE
. (See alsosetrlimit(2)
, which can be used by a process to set the per-process limit,RLIMIT_NOFILE
, on the number of files it may open.) If you get lots of error messages in the kernel log about running out of file handles (look for “VFS: file-max limitreached”), try increasing this value: echo 100000 > /proc/sys/fs/file-max
The kernel constant
NR_OPEN
imposes an upper limit on the value that may be placed in file-max.
Privileged processes (CAP_SYS_ADMIN) can override the file-max limit.
目前系統最大的 FD 值,這個值在開機的時候會被設定。
- 預設值為
8192
- 如果記憶體的十分之一大於預設值,那就不會是 8192,會是記憶體的十分之一大小。
- 例如 c4.xlarge 記憶體為 7.5GiB,所以 file-max 為 760264
- 詳細計算的 source code 參閱:Default value of /proc/sys/fs/file-max 說明
- 需要臨時調整大小,可以直接
echo 100000 > /proc/sys/fs/file-max
,會馬上生效。 - 查詢
file-max
的方法:cat /proc/sys/fs/file-max
sysctl fs.file-max
除了直接改 /proc/sys/fs/file-max
,也可以修改 /etc/sysctl.conf
,如下:
1 | fs.file-max = 100000 |
然後下 sysctl -p
就會馬上生效,或者:
1 | sysctl -w fs.file-max=100000 |
查詢某個 Process 的 FD Limit
直接查詢 /proc/[PID]/limits
就可以知道,設定是否正確被 process 吃到,如下 Max open files
的值就是修改後的:
1 | ~$ cat /proc/26643/limits |
相關應用與問題
- limits.conf 的值可以大於 file-max?
- 可以, 因為 file-max 只是建議值
- FD 跟什麼應用有關係?
- TCP Connection, Log
- Hard Limit 的上限是多少?跟硬體資源有關係?
- 同上,Soft Limit 上限?
- Windows 有 File Descriptor 或者 limit 這種概念?
- 也有,概念不太一樣,參閱 Windows Server 2008 R2 max open files limit
file-max
改很小系統會怎樣?
相關工具
- ulimit
- lsof: list open file
- sysctl: system control
- fuser
- netstat
延伸閱讀
站內資料
參考資料
- Wiki: File Descriptor
- Default value of /proc/sys/fs/file-max
- linux最大文件句柄数量之(file-max ulimit -n limit.conf)