Linux 文件句柄&文件描述符


這里我們先區分好兩個概念:文件描述符和文件句柄

簡單來說,每個進程都有一個打開的文件表(fdtable)。表中的每一項是struct file類型,包含了打開文件的一些屬性比如偏移量,讀寫訪問模式等,這是真正意義上的文件句柄。

文件描述符是一個整數。代表fdtable中的索引位置(下標),指向具體的struct file(文件句柄)。

 

哪些地方會分配文件句柄?

知道文件句柄最終是通過get_empty_filp函數從filp cache中分配的之后,我們順着函數調用鏈路簡單梳理下,就能知道有哪些地方會分配文件句柄了:

  • open系統調用打開文件(path_openat內核函數)
  • 打開一個目錄(dentry_open函數)
  • 共享內存attach (do_shmat函數)
  • socket套接字(sock_alloc_file函數)
  • 管道(create_pipe_files函數)
  • epoll/inotify/signalfd等功能用到的匿名inode文件系統(anon_inode_getfile函數)

file-nr文件里面的第一個字段代表的是內核分配的struct file的個數,也就是文件句柄個數,而不是文件描述符

 

機器上的常常會出現文件句柄使用量與常用的lsof命令的數量相去甚遠的情況

 

 

因為文件描述符和文件句柄是兩個不同的東西:lsof在用戶空間,主要還是從文件描述符的角度來看文件句柄。

我們來做一個實驗:只打開一次文件,然后復制1000次文件描述符。

我們啟動dupfd進程打開了一次/dev/zero文件,復制了1000次文件描述符。file-nr中的文件句柄數只是個位數的變化,而lsof看到的結果漲了1000多。

如果我們把前面的代碼換成open 1000次, 就可以看到file-nr和lsof的輸出幾乎都漲了1000。

我們循環1000次打開/dev/zero文件,之后mmap映射到進程地址空間,然后把這些打開的文件描述符都關掉。很顯然,打開的描述符都被close掉了,不會有什么變化。 那為什么文件句柄數還是增加了1000個左右呢?

原來,linux內核中很多對象都是有引用計數的。 雖然文件句柄是由open先打開的,但mmap之后,引用計數被加1,盡管我們接着把文件描述符close掉了,但是底層指向的struct file由於引用數大於0,不會被回收。

通過上面兩個例子,你應該知道lsof的輸出和實際的文件句柄數有差距的原因了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM