
我希望能夠監控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