有效監控每個進程的 Open FD 數量?

有效監控每個進程的 Open FD 數量?

我希望能夠監控Linux中開啟檔案的數量。目前我正在計算/proc/<pid>/fd和中的文件數量fdinfo

我的負載平衡器有大約一百萬個 FD。所以這最終需要大約 20 秒來執行。

然而,這會導致 CPU 使用率高:47.18% [kernel] [k] __d_lookup

有沒有更有效的方法來取得這個數字?

答案1

對於專用負載平衡器,我會追蹤系統中開啟的檔案總數,而不是浪費 I/O 和 CPU 資源按進程對它們進行計數。不需要的進程剩餘的開啟檔案對於預期結果來說應該是無意義的值。

要了解Linux系統全域開啟的檔案數,不需要統計; Linux 核心會追蹤它開啟的檔案數量。

要知道這一點,請運行:

cat /proc/sys/fs/file-nr | awk ' { print $1 } '

或者

sysctl fs.file-nr | awk ' { print $1 } '

這比計算使用 的輸出開啟的所有檔案要高效得多lsof,後者會遍歷所有/proc/$PID/fd目錄,並對系統 I/O / CPU 資源產生負面影響。

答案2

簡單的:

lsof | wc -l

會告訴您系統中開啟的檔案數。

答案3

此 SystemTap 程式碼對於您的用例來說效率如何?這不是一個完美的視圖,因為它只追蹤從開始時開始的變化(因此在開始之前打開的任何內容都會被錯過),並且需要額外的工作以使輸出更清晰或更合適。

global procfdcount

probe begin {
    printf("begin trace...\n\n")
}

probe syscall.open {
    procfdcount[pid()]++
}

probe syscall.close {
    p = pid()
    procfdcount[p]--
    if (procfdcount[p] < 0) {
        procfdcount[p] = 0
    }
}

probe kprocess.exit {
    p = pid()
    if (p in procfdcount) {
        delete procfdcount[p]
    }
}

probe timer.s(60) {
    foreach (p in procfdcount- limit 20) {
        printf("%d %lu\n", p, procfdcount[p])
    }
    printf("\n")
}

透過類似的方式運行:

... (install systemtap here) ...
# stap-prep
... (fix any reported systemtap issues here) ...
# stap procfdcount.stp

這種方法的缺點是需要識別所有「打開的檔案」(套接字等),然後透過適當的系統呼叫掛鉤(如果可用)調整計數;以上僅追蹤文件檔案。另一種選擇是呼叫task_open_file_handles進入 CPU 的任務,並定期顯示最新的計數。

global taskopenfh

probe begin {
    printf("begin trace...\n\n");
}

probe scheduler.cpu_on {
    p = pid();
    if (p == 0) next;
    taskopenfh[p] = task_open_file_handles(pid2task(p));
}

probe timer.s(60) {
    foreach (p in taskopenfh-) {
        printf("%d %lu\n", p, taskopenfh[p]);
    }
    delete taskopenfh;
    printf("\n");
}

但這會錯過任何不在 CPU 上的東西;完整的清單需要完整的流程和任務,儘管如果您有數百萬個 FD,這可能會太慢或太昂貴。

而且這些探針似乎不穩定,所以也許將來會使用 eBPF 或其他東西?例如 Centos 7 上的第二個在一段時間後爆炸了

ERROR: read fault [man error::fault] at 0x0000000000000008 (((&(fs->fdt))))
near identifier 'task_open_file_handles' at
/usr/share/systemtap/tapset/linux/task.stp:602:10

相關內容