ファイルディスクリプタ
OS がオープンしたファイルやソケットを識別するための整数値
OS低レベル
ファイルディスクリプタとは
ファイルディスクリプタ (File Descriptor, fd) は、OS がオープンしたファイル、ソケット、パイプを識別するための非負整数値である。Unix の「全てはファイル」の思想に基づき、ネットワーク接続もファイルディスクリプタで管理される。
標準のファイルディスクリプタ
| fd | 名前 | 用途 |
|---|---|---|
| 0 | stdin | 標準入力 |
| 1 | stdout | 標準出力 |
| 2 | stderr | 標準エラー出力 |
| 3+ | - | ファイル、ソケット等 |
# リダイレクト
echo "hello" > output.txt # fd 1 (stdout) をファイルに
command 2> error.log # fd 2 (stderr) をファイルに
command > out.log 2>&1 # stdout と stderr を同じファイルに
Node.js との関係
// Node.js の fs モジュールは内部的にファイルディスクリプタを使用
import { open } from 'fs/promises';
const file = await open('/tmp/data.txt', 'r');
console.log(file.fd); // 3 (ファイルディスクリプタ番号)
await file.close(); // fd を解放
ファイルディスクリプタの枯渇
プロセスが使えるファイルディスクリプタには上限がある (デフォルト 1024)。
# 上限の確認
ulimit -n
# 1024
# 上限の変更
ulimit -n 65536
| 原因 | 症状 | 対策 |
|---|---|---|
| ソケットのクローズ忘れ | EMFILE: too many open files |
接続を確実にクローズ |
| DB コネクションリーク | 新しい接続が作れない | コネクションプーリング |
| ファイルのクローズ忘れ | ファイルが開けない | try-finally で確実にクローズ |
Lambda でのファイルディスクリプタ
Lambda の実行環境にもファイルディスクリプタの上限がある (1024)。大量の同時接続 (HTTP リクエスト、DB コネクション) を開くと枯渇する。
lsof でファイルディスクリプタを確認
# プロセスが開いているファイルディスクリプタを表示
lsof -p <PID>
# ソケットのみ表示
lsof -i -p <PID>
epoll / kqueue
Node.js の libuv は、大量のファイルディスクリプタを効率的に監視するために epoll (Linux) / kqueue (macOS) を使用する。イベントループの基盤技術。
ファイルディスクリプタの理解を深めるには関連書籍が参考になる。