文件描述符的数量:/proc/sys/fs/file-nr 和 /proc/$pid/fd 之间不同吗?

HTF*_*HTF 12 linux file-descriptors

我想检查实际使用了多少文件描述符:

cat /proc/sys/fs/file-nr 
12750   0   753795
Run Code Online (Sandbox Code Playgroud)

第一列 (12750) 表示自启动以来分配的文件描述符数。

我想知道为什么以下命令中的数字不同(假设这个班轮返回正确的值:

for pid in $(lsof | awk '{ print $2 }' | uniq); do find /proc/$pid/fd/ -type l 2>&1 | grep -v "No"; done | wc -l

11069

qua*_*nta 12

lsof只列出进程ID。要获取有关线程的信息,您应该使用ps -eLf. 根据man proc

   /proc/[pid]/task(从 Linux 2.6.0-test6 开始)
          这是一个目录,每个目录包含一个子目录
          进程中的线程。每个子目录的名称是
          线程的数字线程 ID ( [tid] )(请参阅gettid(2))。
          在每个子目录中,都有一组文件
          具有与/proc/[pid]相同的名称和内容
          目录。对于所有线程共享的属性,task/[tid]
          下每个文件的内容
          子目录将与相应文件中的相同
          在父/proc/[pid]目录中(例如,在多线程
          过程中,所有的task/[tid]/cwd文件都将具有相同的
          值作为父目录中的/proc/[pid]/cwd文件,
          因为进程中的所有线程共享一个工作
          目录)。对于每个线程不同的属性,task/[tid]
          下对应的文件可能有不同
          值(例如,每个任务/[tid]/状态
          文件中的各个字段对于每个线程可能不同)。
在多线程进程中, /proc/[pid]/任务目录不可用,如果主 线程已经终止(通常通过调用 pthread_exit(3) )。

我将通过运行来计算打开的文件描述符的数量:

ps -eL | awk 'NR > 1 { print $1, $2 }' | \
while read x; do \
    find /proc/${x% *}/task/${x#* }/fd/ -type l; \
done | wc -l
Run Code Online (Sandbox Code Playgroud)

结果是 17270。

让我们看看自启动以来分配了多少文件描述符:

cat /proc/sys/fs/file-nr 
11616   0   398855
Run Code Online (Sandbox Code Playgroud)

为什么文件描述符/proc/[pid]/task/[tid]/fd的数量超过分配的文件句柄数量/proc/sys/fs/file-nr?我想它们是由forked 子进程创建的:

man fork

子进程继承父进程打开的文件描述符集的副本

man pthreads

POSIX.1 还要求线程共享一系列其他属性(即这些属性是进程范围的而不是每个线程的): - 进程 ID

  • 父进程 ID

  • 进程组 ID 和会话 ID

  • 控制终端

  • 用户和组 ID

  • 打开文件描述符

  • 我不认为 /proc/sys/fs/file-nr 中较高的数字是由于分叉进程造成的。请参阅此处的第一个答案:http://unix.stackexchange.com/questions/176967/why-file-nr-and-lsof-count-on-open-files-differs 以及此处的引用:(..但是当应用程序释放这些文件句柄时,内核不会释放它们。内核会回收这些文件句柄。) https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/5/html/Tuning_and_Optimizing_Red_Hat_Enterprise_Linux_for_Oracle_9i_and_10g_Database Oracle_9i_and_10g_Tuning_Guide-Setting_File_Handles.html (2认同)