ファイルディスクリプタ

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) を使用する。イベントループの基盤技術。

ファイルディスクリプタの理解を深めるには関連書籍が参考になる。

関連用語