搜尋
首頁運維linux運維檔案描述符與FILE概念介紹

檔案描述符與FILE概念介紹

Jun 21, 2017 pm 01:44 PM
file文件

1. 文件描述符(重點)

在Linux系統中一切皆可以看成是文件,文件又可分為:普通文件、目錄文件、連結文件和設備文件。文件描述符(file descriptor)是內核為了高效管理已被打開的文件所創建的索引,其是一個非負整數(通常是小整數),用於指代被打開的文件,所有執行I/O操作的系統呼叫都通過檔案描述符。程式剛啟動的時候,0是標準輸入,1是標準輸出,2是標準錯誤。如果此時去開啟一個新的文件,它的文件描述會是3。

1.1概念介紹

檔案描述子的運算(如: open(),creat(),close(),read()))返回的是一個檔案描述子,它是int類型的整數,即fd,其本質是檔案描述子表中的下標,它起到一個索引的作用,進程透過PCB中的檔案描述子表找到該fd所所指的文件指標filp。每個進程在PCB(Process Control Block)即進程控制塊中都保存著一份文件描述符表,而文件描述符就是這個表的索引,文件描述表中每個表項都有一個指向已打開文件的指標; 已開啟的檔案在核心中以file結構體表示,檔案描述子表中的指標指向file結構體。每打開一個文件,fd預設從最小的未被使用的下標開始分配。文件描述符的缺點:不能移植到UNIX以外的系統上去,也不直觀。

下面畫張圖來表示它們之間的關係:

 而每個檔案中又主要包含以下這些資訊:

1.2圖表解釋

file結構體中維護File Status Flag(file結構體的成員f_flags)和目前讀寫位置(file結構體的成員f_pos)。在上圖中,進程1和進程2都開啟相同文件,但對應不同的file結構體,因此可以有不同的File Status Flag和讀寫位置。 file結構體中比較重要的成員還有f_count,表示引用數數(Reference Count),後面我們會講到,dupfork 等系統呼叫會導致多個檔案描述子指向同一個file結構體,例如有fd1fd2都引用同一個 file結構體,那麼它的引用計數就是2,當close(fd1)時並不會釋放file結構體,而只是把引用計數減到1,如果再close(fd2),引用計數就會減少到0同時釋放file結構體,這才真的關閉了檔案。

每個file結構體都指向一個file_operations結構體,這個結構體的成員都是函數指針,指向實作各種檔案操作的核心函數。例如在使用者程式中read一個檔案描述符,read#透過系統呼叫進入內核,然後找到這個檔案描述符所指向的file結構體,找到file結構體所指向的file_operations結構體,呼叫它的read成員所指向的核心函數以完成使用者請求。在使用者程式中呼叫lseekreadwriteioctlopen等函數,最後都由核心呼叫file_operations的各成員所指向的核心函數完成使用者請求。 file_operations結構體中的release成員用來完成使用者程式的close請求,之所以叫release而不叫 close是因為它不一定真的關閉文件,而是減少引用計數,只有引用計數減到0才關閉文件。對於同一個檔案系統上開啟的常規檔案來說,readwrite等檔案操作的步驟和方法應該是一樣的,呼叫的函數應該是相同的,所以圖中的三個開啟檔案的file結構體指向同一個file_operations結構體。如果開啟一個字元設備文件,那麼它的readwrite操作肯定和常規文件不一樣,不是讀寫磁碟的資料塊而是讀寫硬體設備,所以file結構體應該指向不同的file_operations結構體,其中的各種檔案操作函數由該裝置的驅動程式實作。

每個file結構體都有一個指向dentry結構體的指針,「dentry」是directory entry(目錄項目)的縮寫。我們傳給openstat等函數的參數的是路徑,例如/home/akaedu/a,需要根據路徑找到檔案的inode。為了減少讀盤次數,核心快取了目錄的樹狀結構,稱為dentry cache,其中每個節點是一個dentry結構體,只要沿著路徑各部分的dentry搜尋即可,從根目錄/找到home目錄,然後找到akaedu目錄,然後找到檔案a。 dentry cache只保存最近造訪過的目錄項,如果要找的目錄項在cache中沒有,就要從磁碟讀到記憶體。

每個dentry結構體都有一個指標指向inode結構體。 inode結構體保存著從磁碟inode讀上來的資訊。在上圖的例子中,有兩個dentry,分別表示/home/akaedu/a/home/akaedu/b,它們都指向同一個inode,說明這兩個文件互為硬連結。 inode結構體中保存著從磁碟分割區的inode讀取上來訊息,例如擁有者、檔案大小、檔案類型和權限位元等。每個inode結構體都有一個指向inode_operations結構體的指針,後者也是一組函數指針指向一些完成文件目錄操作的內核函數。和file_operations不同,inode_operations所指向的不是針對某一個檔案進行操作的函數,而是影響檔案和目錄佈局的函數,例如新增刪除檔案和目錄、追蹤符號鏈接等等,屬於同一檔案系統的各inode結構體可以指向同一個inode_operations結構體。

inode結構體有一個指向super_block結構體的指標。 super_block結構體保存著從磁碟分割區的超級區塊讀取上來的信息,例如檔案系統類型、區塊大小等。 super_block結構體的s_root成員是指向dentry的指針,表示這個檔案系統的根目錄被mount到哪裡,在上圖的例子中這個分割區被mount/home目錄下。

filedentryinodesuper_block這幾個結構體組成了VFS(虛擬檔案系統VFS ,Virtual Filesystem)的核心概念。

1.3對檔案描述符的操作

(1).查看Linux檔案描述子

 1 [root@localhost ~]# sysctl -a | grep -i file-max --color 3 fs.file-max = 392036 5 [root@localhost ~]# cat /proc/sys/fs/file-max 7 392036 9 [root@localhost ~]# ulimit -n11 102413 [root@localhost ~]#

Linux下最大檔案描述子的限制有兩個方面,一個是用戶級的限制,另外一個則是系統級限制。

系統級限制:sysctl命令和proc檔案系統中查看到的數值是一樣的,這屬於系統級限制,它是限制所有使用者開啟檔案描述符的總和

用戶級限制:ulimit指令看到的是用戶級的最大檔案描述符限制,也就是說每個用戶登入後執行的程式佔用檔案描述符的總數不能超過這個限制

(2).修改檔案描述子的值

1 [root@localhost ~]# ulimit-SHn 102402 [root@localhost ~]# ulimit  -n3 102404 [root@localhost ~]#

以上的修改只對目前會話起作用,是臨時性的,如果需要永久修改,則要修改如下:

1 [root@localhost ~]# grep -vE'^$|^#' /etc/security/limits.conf2 *                hard nofile                  40963 [root@localhost ~]#
1 //默认配置文件中只有hard选项,soft 指的是当前系统生效的设置值,hard 表明系统中所能设定的最大值2 [root@localhost ~]# grep -vE'^$|^#' /etc/security/limits.conf3 *      hard         nofile       102404 *      soft         nofile      102405 [root@localhost ~]#6 // soft

(3).修改系統限制

1 [root@localhost ~]# sysctl -wfs.file-max=4000002 fs.file-max = 4000003 [root@localhost ~]# echo350000 > /proc/sys/fs/file-max  //重启后失效4 [root@localhost ~]# cat /proc/sys/fs/file-max5 3500006 [root@localhost ~]#

//以上是暫時修改檔案描述符
//永久修改把fs.file-max=400000加入/etc/sysctl.conf中,使用sysctl -p即可

1.4用程式檢視檔案描述子

下面的程序,打開/home/shenlan/hello.c文件,如果此目錄下沒有hello.c文件,程式自動創建,程式中傳回的文件描述符為3。因為進程啟動時,開啟了標準輸入(0)、標準輸出(1)和標準出錯處理(2)三個文件,fd預設從最小的未被使用的下標開始分配,因此傳回的檔案描述符為3

 1 #include<stdio.h> 2 #include<sys> 3 #include<sys> 4 #include<fcntl.h> 5 #include<stdlib.h> 6 int main() 7 { 8        int fd; 9        if((fd = open("/home/shenlan/fd.c",O_CREAT|O_WRONLY|O_TRUNC,0611))</stdlib.h></fcntl.h></sys></sys></stdio.h>
#

执行结果:

1.5进程打开一个文件的具体流程    

进程通过系统调用open( )来打开一个文件,实质上是获得一个文件描述符,以便进程通过文件描述符为连接对文件进行其他操作。进程打开文件时,会为该文件创建一个file对象,并把该file对象存入进程打开文件表中(文件描述符数组),进而确定了所打开文件的文件描述符。        open( )操作在内核里通过sys_open( )实现的,sys_open( )将创建文件的dentryinodefile对象,并在file_struct结构体的进程打开文件表fd_array[NR_OPEN_DEFAULT]中寻找一个空闲表项,然后返回这个表项的下标(索引),即文件描述符。创建文件的file对象时,将file对象的f_op指向了所属文件系统的操作函数集file_operations,而该函数集又来自具体文件的i节点,于是虚拟文件系统就与实际文件系统的操作衔接起来了。

 2.C标准库中的FILE结构和文件描述符

C语言中使用的是文件指针而不是文件描述符做为I/O的句柄."文件指针(file pointer)"指向进程用户区中的一个被称为FILE结构的数据结构。FILE结构包括一个缓冲区和一个文件描述符值.而文件描述符值是文件描述符表中的一个索引.从某种意义上说文件指针就是句柄的句柄。流(如: fopen)返回的是一个FILE结构指针, FILE结构是包含有文件描述符的,FILE结构函数可以看作是对fd直接操作的系统调用的封装, 它的优点是带有I/O缓存。

从文件描述符fd 到文件流 FILE* 的函数是
FILE* fdopen(int filedes,const char* mode);

早期的C标准库中,FILEstdio.h中定义Turbo C中,参见谭浩强的《C程序设计》,FILE结构体中包含成员fd,即文件描述符。亦可以在安装的Ubuntu系统的/usr/include/stdio.h中找到struct _IO_FILE结构体,这个结构体比较复杂,我们只关心需要的部分-文件描述符,但是在这个的结构体中,我们并没有发现与文件描述符相关的诸如fd成员变量。此时,类型为int_fileno结构体成员引起了我们的注意,但是不能确定其为文件描述符。因此写个程序测试是最好的办法,可以用以下的代码测试:

 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<sys> 4 #include<sys> 5 #include<fcntl.h> 6 int main( ) 7 { 8        char buf[50] = {"ILOVE this game!"}; 9        FILE *myfile;10 11        myfile = fopen("2.txt","w+");12        if(!myfile){13               printf("error:openfile failed!\n");14        }15        printf("The openedfile's descriptor is %d\n",myfile->_fileno);16        if(write(myfile->_fileno,buf,50)</fcntl.h></sys></sys></stdlib.h></stdio.h>

程式中,使用fopen函數以讀寫開啟2.txt文件,如果不存在2.txt文件,則建立此文件。並將其傳回的FILE指標myfile。使用printf向標準終端印出myfile->_fileno的值,並將myfile->_fileno作為檔案描述子傳遞給write 系統調用,向開啟的檔案寫入緩衝區資料。然後使用cat指令查看2.txt的內容。執行的結果如圖所示。 _fileno的值為3,因為標準輸入、輸出、出錯為012。輸出結果如下:
    因此,_fileno成員即為作業系統開啟檔案傳回的句柄(windows系統)或檔案描述子。深入學習可以閱讀人民郵電出版社《C標準庫》。當然也可以閱讀/glibc-2.9/manual/io.txti檔。在 Linux中,檔案的描述子分配是從小到大逐個查詢檔案描述子是否已經使用,然後再分配,也可以寫程式測試。

 檔案描述子表也稱為檔案描述子數組,其中存放了一個進程所開啟的所有檔案。檔案描述符數組包含在進程開啟的檔案表files_struct結構中。 /include/linux/fdtable.h中定義,為一個指向file類型的指標陣列---fd_array[NR_OPEN_DEFAULT],其中NR_OPEN_DEFAULT也在fdtable.h中定義,這是一個和具體的CPU體系結構有關的變量,#define NR_OPEN_DEFAULTBITS_PER_LONG#。

#FILE結構和檔案描述子、file結構之間的關係可以用下圖來表示:

#

以上是檔案描述符與FILE概念介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
掌握Linux操作:實用指南掌握Linux操作:實用指南Apr 12, 2025 am 12:10 AM

掌握Linux操作的原因是其廣泛的應用場景和強大的功能。 1)Linux適合開發者、系統管理員和技術愛好者,應用於服務器管理、嵌入式系統和容器化技術。 2)學習Linux可以從文件系統結構、Shell使用、用戶權限管理和進程管理入手。 3)Linux命令行是其核心工具,通過Shell執行命令,如ls、mkdir、cd等,支持重定向和管道操作。 4)高級用法包括編寫自動化腳本,如備份腳本,使用tar命令和條件判斷。 5)常見錯誤包括權限、路徑和語法問題,可通過echo、set-x和$?調試。 6)性能優化建議

Linux的5支支柱:了解他們的角色Linux的5支支柱:了解他們的角色Apr 11, 2025 am 12:07 AM

Linux系統的五大支柱是:1.內核,2.系統庫,3.Shell,4.文件系統,5.系統工具。內核管理硬件資源並提供基本服務;系統庫為應用程序提供預編譯函數;Shell是用戶與系統交互的接口;文件系統組織和存儲數據;系統工具用於系統管理和維護。

Linux維護模式:工具和技術Linux維護模式:工具和技術Apr 10, 2025 am 09:42 AM

在Linux系統中,可以通過在啟動時按特定鍵或使用命令如“sudosystemctlrescue”進入維護模式。維護模式允許管理員在不受干擾的情況下進行系統維護和故障排除,如修復文件系統、重置密碼、修補安全漏洞等。

關鍵Linux操作:初學者指南關鍵Linux操作:初學者指南Apr 09, 2025 pm 04:09 PM

Linux初學者應掌握文件管理、用戶管理和網絡配置等基本操作。 1)文件管理:使用mkdir、touch、ls、rm、mv、cp命令。 2)用戶管理:使用useradd、passwd、userdel、usermod命令。 3)網絡配置:使用ifconfig、echo、ufw命令。這些操作是Linux系統管理的基礎,熟練掌握它們可以有效管理系統。

如何使用sudo向Linux的用戶授予高架特權?如何使用sudo向Linux的用戶授予高架特權?Mar 17, 2025 pm 05:32 PM

本文解釋瞭如何管理Linux中的Sudo特權,包括授予,撤銷和安全性最佳實踐。關鍵重點是安全和sudoers安全和限制訪問。Character數量:159

如何在Linux中實現SSH的兩因素身份驗證(2FA)?如何在Linux中實現SSH的兩因素身份驗證(2FA)?Mar 17, 2025 pm 05:31 PM

本文提供了有關使用Google Authenticator在Linux上設置兩因素身份驗證(2FA)的指南,詳細介紹了安裝,配置和故障排除步驟。它突出了2FA的安全益處,例如增強的SEC

如何使用TOP,HTOP和VMSTAT等工具來監視Linux中的系統性能?如何使用TOP,HTOP和VMSTAT等工具來監視Linux中的系統性能?Mar 17, 2025 pm 05:28 PM

本文討論了使用TOP,HTOP和VMSTAT監視Linux系統性能,並詳細介紹其獨特功能和自定義選項,以進行有效的系統管理。

如何使用軟件包管理器(APT,YUM,DNF)管理Linux中的軟件包?如何使用軟件包管理器(APT,YUM,DNF)管理Linux中的軟件包?Mar 17, 2025 pm 05:26 PM

文章討論了使用APT,YUM和DNF在Linux中管理軟件包,涵蓋安裝,更新和刪除。它比較了它們對不同分佈的功能和適用性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

EditPlus 中文破解版

EditPlus 中文破解版

體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器