Linux下的文件系統爲樹形結構,入口爲/ 樹形結構下的文件目錄: 不管哪一個版本的Linux系統,都有這些目錄,這些目錄應該是標準的。各個Linux發行版本會存在一些小小的差別,但整體來講,仍是大致差很少。 1. / 文件系統的入口,最高一級目錄; 2. /bin 基礎系統所須要的命令位於此目錄,是最小系統所須要的命令,如:ls, cp, mkdir等。這個目錄中的文件都是可執行的,通常的用戶均可以使用。 3. /boot 包含Linux內核及系統引導程序所須要的文件,好比 vmlinuz initrd.img 文件都位於這個目錄中。在通常狀況下,GRUB或LILO系統引導管理器也位於這個目錄; 4. /dev 設備文件存儲目錄,好比聲卡、磁盤... ... 這是一個很是有趣的目錄,是Linux文件系統的一個閃亮的特性 - 全部對象都是文件或目錄。仔細觀察這個目錄你會發現hda1, hda2等, 它們表明系統主硬盤的不一樣分區。/dev/cdrom和/dev/fd0表明你的CDROM驅動器和floppy驅動器。看上去可能有些奇怪,但比較文件和硬件的特性這倒是十分合理的。它們均可以讀出和寫入。例如/dev/dsp,這個文件表明你的揚聲器。那麼寫入這個文件的數據都回傳送到喇叭。試一試 'cat /etc/lilo.conf > /dev/dsp' 你會聽到一些聲音。這是你的 lilo.conf 文件的聲音!一樣,向 /dev/ttyS0 ( COM 1 ) 讀出或寫入數據你能夠和接到上面的設備進行通信。 5. /etc 存放系統程序或者通常工具的配置文件。如安裝了apache2以後,配置文件在/etc/apache2/目錄下。/etc/init.d 這個目錄是用來存放系統或服務器以System V模式啓動的腳本,這在以System V模式啓動或初始化的系統中常見。如apache2的/etc/init.d apache2 start|stop|restart MySQL爲/etc/init.d mysql start|stop|restart 6. /home 普通用戶默認存放目錄 Linux 是多用戶環境,因此每個用戶都有一個只有本身能夠訪問的目錄(固然管理員也能夠訪問)。它們以 /home/username 的方式存在。這個目錄也保存一些應用對於這個用戶的配置,好比 IRC, X 等。 7. /lib 庫文件存放目錄這裏包含了系統程序所須要的全部共享庫文件,相似於 Windows 的共享庫 DLL 文件。 8. /lost+found 在ext2或ext3文件系統中,當系統意外崩潰或機器意外關機,而產生一些文件碎片放在這裏。當系統啓動的過程當中fsck工具會檢查這裏,並修復已經損壞的文件系統。 有時系統發生問題,有不少的文件被移到這個目錄中,可能會用手工的方式來修復,或移到文件到原來的位置上。Linux 應該正確的關機。但有時你的系統也可能崩潰掉或忽然斷電使系統意外關機。那麼啓動的時候 fsck 將會進行長時間的文件系統檢查。Fsck 會檢測並試圖恢復所發現的不正確的文件。被恢復的文件會放置在這個目錄中。所恢復的文件也許並不完整或並不合理,但畢竟提供了一些恢復數據的機會。 9. /media 即插即用型存儲設備的掛載點自動在這個目錄下建立,好比USB盤系統自動掛載後,會在這個目錄下產生一個目錄 ;CDROM/DVD自動掛載後,也會在這個目錄中建立一個目錄,相似cdrom 的目錄。這個只有在最新的發行套件上纔有. 10. /mnt /mnt 這個目錄通常是用於存放掛載儲存設備的掛載目錄的,好比有cdrom 等目錄。有時咱們能夠把讓系統開機自動掛載文件系統,把掛載點放在這裏也是能夠的。好比光驅能夠掛載到/mnt/cdrom 。 這是一個普通的加載目錄,在這裏你能夠加載你的文件系統或設備。加載是使一個文件系統對於系統可用的過程。在加載後你的文件能夠在加載目錄下訪問。這個目錄一般包含加載目錄或用於加載軟驅和光驅的子目錄。若是須要,你也能夠在這裏創建其它的加載目錄。對於加載目錄的位置並無強制性的要求,你能夠在系統的任意位置創建加載目錄。創建 /mnt 只是爲了使系統更工整的慣例。 11. /opt 表示的是可選擇的意思,有些軟件包也會被安裝在這裏,也就是自定義軟件包,好比在Fedora Core 5.0中,OpenOffice就是安裝在這裏。有些咱們本身編譯的軟件包,就能夠安裝在這個目錄中;經過源碼包安裝的軟件,能夠經過 ./configure --prefix=/opt/,將軟件安裝到opt目錄。 這個目錄包含全部默認系統安裝以外的軟件和添加的包。 12. /proc 操做系統運行時,進程(正在運行中的程序)信息及內核信息(好比cpu、硬盤分區、內存信息等)存放在這裏。/proc目錄是假裝的文件系統proc的掛載目錄,proc並非真正的文件系統。這是系統中極爲特殊的一個目錄,實際上任何分區上都不存在這個目錄。它實際是個實時的、駐留在內存中的文件系統。 13. /root Linux超級權限用戶root的家目錄; 14. /sbin 大可能是涉及系統管理的命令的存放,是超級權限用戶root的可執行命令存放地,普通用戶無權限執行這個目錄下的命令;這個目錄和/usr/sbin; /usr/X11R6/sbin或/usr/local/sbin 目錄是類似的; 咱們記住就好了,凡是目錄sbin中包含的都是root權限才能執行的。 15. /tmp 臨時文件目錄,有時用戶運行程序的時候,會產生臨時文件。 /tmp就用來存放臨時文件的。/var/tmp目錄和這個目錄類似。許多程序在這裏創建lock文件和存儲臨時數據。有些系統會在啓動或關機時清空此目錄。 16. /usr 這個是系統存放程序的目錄,好比命令、幫助文件等。這個目錄下有不少的文件和目錄。當咱們安裝一個Linux發行版官方提供的軟件包時,大多安裝在這裏。若是有涉及服務器配置文件的,會把配置文件安裝在/etc目錄中。 /usr目錄下包括:涉及字體目錄/usr/share/fonts ,幫助目錄 /usr/share/man或/usr/share/doc,普通用戶可執行文件目錄/usr/bin 或/usr/local/bin 或/usr/X11R6/bin ,超級權限用戶root的可執行命令存放目錄,好比 /usr/sbin 或/usr/X11R6/sbin 或/usr/local/sbin 等;還有程序的頭文件存放目錄/usr/include。 /usr/bin 這個目錄是可執行程序的目錄,普通用戶就有權限執行; 當咱們從系統自帶的軟件包安裝一個程序時,他的可執行文件大多會放在這個目錄。/usr/sbin 這個目錄也是可執行程序的目錄,但大多存放涉及系統管理的命令。只有root權限才能執行;類似目錄是/sbin 或/usr/local/sbin或/usr/X11R6/sbin等; /usr/local 這個目錄通常是用來存放用戶自編譯安裝軟件的存放目錄;通常是經過源碼包安裝的軟件,若是沒有特別指定安裝目錄的話,通常是安裝在這個目錄中。這個目錄下面有子目錄。/usr/lib 和/lib 目錄類似,是庫文件的存儲目錄;/usr/share 系統共用的東西存放地,好比 /usr/share/fonts 是字體目錄,是用戶都共用的吧。/usr/share/doc和/usr/share/man幫助文件,也是共用的吧; /usr/src 是內核源碼存放的目錄,好比下面有內核源碼目錄,好比 linux 、linux-2.xxx.xx 目錄等。有的系統也會把源碼軟件包安裝在這裏。好比Fedora/Redhat,當咱們安裝file.src.rpm的時候,這些軟件包會安裝在 /usr/src/redhat相應的目錄中。請參考: 《file.src.rpm 使用方法的簡單介紹》 。另外Fedhat 4.0 5.0,他的內核源碼包的目錄位於/usr/src/kernels目錄下的某個目錄中(只有安裝後纔會生成相應目錄); 17. /var 這個目錄的內容是常常變更的,看名字就知道,咱們能夠理解爲vary的縮寫,/var下有/var/log 這是用來存放系統日誌的目錄。/var/www目錄是定義Apache服務器站點存放目錄;/var/lib 用來存放一些庫文件,好比MySQL的,以及MySQL數據庫的的存放地;/var/log 系統日誌存放,分析日誌要看這個目錄的東西;/var/spool 打印機、郵件、代理服務器等假脫機目錄; Windows和Linux文件系統的區別 Linux文件系統與Windows文件系統有很大的差異。Linux文件系統做爲開端,只有一個單獨的頂級目錄結構。全部一切都從 '根' 開始,用 '/' 表明, 而且延伸到子目錄。DOS/Windows有不一樣的分區,同時目錄都存於分區上。linux則經過 '加載' 的方式把全部分區都放置在 '根' 下制定的目錄裏。一句話總結:Windows下,目錄結構屬於分區;Linux下,分區 '加載' 於目錄結構。 在Windows下, 啓動時檢測不一樣的分區並被賦予一個分區字母。在Linux下除非你加載一個分區或設備,不然系統不會知道那個分區的存在。這看上去也許不是訪問分區或設備的最方便的方式,可是這種方式提供了偉大的機動性。這種構建的方式被稱爲統一的文件系統,超越了Windows所使用的方式。舉個使用 /usr 的例子。這個目錄包含了大多數的系統可執行文件。在Linux文件系統下,你能夠選擇把它加載爲其餘分區甚至網絡上的其餘計算機。系統不會感知其中的不一樣,由於它表現出的只是本地目錄結構下衆多的目錄中的一個而已。你是否有妄圖在Windows下移動可執行文件和數據,而獲得的是不得不去修改註冊表或乾脆藍屏?你可曾奢望過移動 C: 到其餘分區上?
存儲設備進行格式化(即創建文件系統)html
1。關於文件系統node
對存儲設備分區仍是不夠的,咱們還要對新增分區進行格式化;一個分區只有創建了某種文件系統後,這個分區才能使用;創建文件系統過程,就是用相應格式化工具格式化分區的過程,這個過程和咱們在Windows中格式化某個分區爲NTFS分區相似;沒有什麼高深的內容,只是所用的工具不同罷了;mysql
Linux操做系統中,幾乎支持目前主流的文件系統,好比NTFS(只讀)、FAT(可讀可寫)、ext二、ext三、reiserfs、hfs (MAC 操做系統的文件系統)、swap 交換分區... ... 還有一些我們不熟悉的操做系統的文件系統等;linux
在Linux中,咱們經常使用的文件系統無非是上面例出的這些;若是您新增了一個硬盤,可能想格 式化成 Linux的文件系統,最佳選擇是 reiserfs 或ext3;目前ext2已被 ext3取代;咱們不推薦用ext2文件系統,ext2的使用風險比較大;速度最快的文件系統,當屬reiserfs;reiserfs 還有不少優勢,好比更安全;ext3是Redhat認爲最好的文件系統。sql
相對來講reiserfs仍是比ext3要優秀。shell
文件系統概念數據庫
1。*nix系統中:一切皆文件;apache
2。文件編程
a. )文件的成分: 不管文件是一個程序、一個文檔、一個數據庫,或者是一個目錄,操做系統都會賦予它以下所示的一樣的結構:
◆索引節點又稱I節點,在文件系統結構中,包含有關相應文件的信息的一個記錄,這些信息包括文件權限、文件主、文件大小、存放位置、創建日期等。
◆數據文件的實際內容,它能夠是空的,也能夠很是大,而且有本身的結構。ubuntu
b.) Linux系統區分文件名的大小寫
以圓點「.」開頭的文件名是隱含文件(dot files),默認方式下使用ls命令並不能把它們在屏幕上顯示出來。一樣,在默認狀況下,Shell通配符並不匹配這類文件名。
c.) 文件名通配符
星號(*): 與0個或多個任意的字符相匹配
問號(?): 問號只與一個任意的字符匹配,可使用多個問號
方括號([ ]) : 與問號類似,只與一個字符匹配。它們的區別在於,問號與任意一個字符匹配,而方括號只與括號中列出的字符之一匹配。例如letter [123]只與文件letter一、letter2或letter3匹配,但不與文件 letter12匹配。能夠用短橫線表明一個範圍內的字符,而不用將它們一一列出。例如,letter[1-3]是letter[123]的簡寫形式。可是,要注意範圍內的字符都按升序排列,即[A-Z]是有效的,而[Z-A]是無效的。方括號中能夠列出多個範圍,如[A-Za-z]能夠和任意大寫或小寫 的字符相匹配。方括號中若是以驚歎號「!」開始,表示不與驚歎號後的字符匹配。
文件類型
Linux操做系統支持普通文件、目錄文件、特別文件及符號連接文件等文件類型。
1. 普通文件
普通文件也稱做常規文件,包含各類長度的字節串。核心對這些數據沒有進行結構化,只是做爲有序的字節序列把它提交給應用程序。應用程序本身組織和解釋這些數據,一般把它們歸併爲下述類型之一:
◆文本文件,由ASCII字符構成。例如,信件、報告和稱做腳本(Script)的命令文本文件,後者由shell解釋執行。
◆數據文件,由來自應用程序的數字型和文本型數據構成。例如,電子表格、數據庫,以及字處理文檔。
◆可執行的二進制程序,由機器指令和數據構成。例如,上面所說的系統提供的命令。
使用file命令能夠肯定指定文件的類型。該命令能夠將任意多個文件名當作參數,其通常使用格式是:file 文件名 [文件名...]
2. 目錄
目錄是一類特殊的文件,利用它能夠構成文件系統的分層樹型結構。如同普通文件那樣,目錄文件也包含數據;但目錄文件與普通文件的差異是,核心對這些數據加以結構化,它是由成對的「I節點號/文件名」構成的列表。
◆I節點號是檢索I節點表的下標,I節點中存放有文件的狀態信息。
◆文件名是給一個文件分配的文本形式的字符串,用來標識該文件。在一個指定的目錄中,任何兩項都不能有一樣的名字。
每一個目錄的第一項都表示目錄自己,並以「.」做爲它的文件名。每一個目錄的第二項的名字是「..」,表示該目錄的父目錄。
應注意:以「.」開頭的文件名錶示隱含文件,使用帶-a選項的ls命令能夠列出它們。
當把文件添加到一個目錄中的時候,該目錄的大小會增加,以便容納新文件名。當刪除文件時,目錄的尺寸並不減小,而是核心對該目錄項作上特殊標記,以便下次添加一個文件時從新使用它。ls命令不會列出這些未被使用的項。
Linux系統的目錄結構
Linux文件系統採用帶連接的樹形目錄結構,即只有一個根目錄(一般用「/」表示),其中含有下級子目錄或文件的信息;子目錄中又可含有更下級的子目錄或者文件的信息。這樣一層一層地延伸下去,構成一棵倒置的樹,如圖1所示。
圖1 Linux樹型目錄結構
在目錄樹中,根節點和中間節點(用圓圈表示)都必須是目錄,而普通文件和特別文件只能做爲「葉子」出現。固然,目錄也能夠做爲葉子。
(1)用戶主目錄
當註冊進入系統時,主目錄就是當前工做目錄。主目錄每每位於/home目錄之下,而且與註冊名相同,例如,/home/mengqc。一般主目錄包含子目錄、數據文件,以及用於註冊環境的配置文件。
絕對路徑和相對路徑
什麼狀況下使用絕對路徑名,什麼狀況下使用相對路徑名,取決於哪一種方式涉及到的目錄更少。路徑短,不只鍵盤輸入少,並且節省系統搜索路徑的時間,提升執行效率。例如,當前的工做目錄是 /etc/conf/cf.d,若是須要訪問系統口令文件/etc/passwd,那麼使用絕對路徑名是/etc/passwd,使用相對路徑名是.. /../passwd。絕對路徑名/etc/passwd涉及的目錄有2個,而相對路徑名../../passwd涉及的目錄倒是3個。此時,使用絕對路 徑名更有效。
可是,若是當前工做目錄是/home/mengqc/lib,要訪問在 func目錄之下的file1文件,那麼使用絕對路徑名是/home/mengqc/lib/func/file1,使用相對路徑名是 func/file1。絕對路徑名/home/mengqc/lib/func/file1涉及的目錄有5個,而相對路徑名涉及的目錄只有2個。此時,使用相對路徑名更有效。
若是不清楚當前工做目錄與其它目錄之間的關係,那麼最好使用絕對路徑名。
3. 設備文件
在Linux系統中,全部設備都做爲一類特別文件對待,用戶像使用普通文件那樣對設備進行操做,從而實現設備無關性。可是,設備文件除了存放在文件I節點中的信息外,它們不包含任何數據。系統利用它們來標識各個設備驅動器,核心使用它們與硬件設備通訊。
有兩類特別設備文件,它們對應不一樣類型的設備驅動器:
◆字符設備 最經常使用的設備類型,容許I/O傳送任意大小的數據,取決於設備自己的容量。使用這種接口的設備包括終端、打印機及鼠標。
◆塊設備 這類設備利用核心緩衝區的自動緩存機制,緩衝區進行I/O傳送老是以1KB爲單位。使用這種接口的設備包括硬盤、軟盤和RAM盤。
Linux系統的文件系統路徑
1。路徑分爲絕對路徑和相對路徑。
絕對路徑是從/(也被稱爲根目錄)開始的,好比/usr、/etc/X11。若是一個路徑是從/開始的,它必定是絕對路徑。
相對路徑是以 . 或 .. 開始的,.表示用戶當前操做所處的位置,而.. 表示上級目錄;在路徑中,.表示用戶當前所處的目錄,而..上級目錄,要把.和..當作目錄來看。
2。[root@localhost ~]# pwd 注:判斷用戶當前所處的位置,也就是說他到底位於哪?
use when you are lost.
3。
[root@localhost ~]# cd . 注:咱們進入。
[root@localhost ~]# cd .. 注:咱們切入/root的上級目錄。
注意,cd以後有個空格。
4。~ 表示當前用戶本身的家目錄;
~USER 表示用戶名爲USER的家目錄
如:
cd ~ 回到當前用戶的家目錄;
cd ~USERNAME 回到USERNAME用戶的家目錄;
文件系統及其安裝
一個硬盤上能夠同時存在多個文件系統,每一個文件系統佔據硬盤的一個獨立分區。Linux文件系統能夠根據須要隨時裝卸,從而實現文件存儲空間的動態擴充和信息安全。在系統初啓時,每每只有一個文件系統被安裝上,即根文件系統,其上的文件主要是保證系統正常運行的操做系統的代碼文件,以及若干語言編譯程序、命令解釋程序和相應的命令處理程序等構成的文件,此外,還有大量的用戶文件空間。根文件系統一旦安裝上,則在整個系統運行過程當中是不能卸下的,它是系統的基本部分。
其它的文件系統(例如,由軟盤構成的文件系統)能夠根據須要(如從硬盤向軟盤複製文件),做爲子系統動態地安裝到主系統中,如圖5所示。其中,mnt是爲安裝子文件系統而特設的安裝節點。
圖5 文件系統安裝
通過安裝以後,主文件系統與子文件系統就構成一個有完整目錄層次結構的、容量更大的文件系統。這種安裝能夠高達幾級。就是說,若干子文件系統能夠並列安裝到主文件系統上,也能夠一個接一個地串連安裝到主文件系統上。
已安裝的子文件系統也可從整個文件系統上卸下來,恢復安裝前的獨立狀態。
1.創建文件系統
當硬盤完成分區後,應該在該分區上創建文件系統。這一步工做是經過mkfs工具來完成的。例如,若是須要在分區/dev/hda1上創建ext2文件系統,並檢查壞塊,應該使用如下命令:
# mkfs -c /dev/hda1
注意,只有root用戶才能創建或安裝/卸下文件系統。
2.安裝文件系統
建立文件系統後,須要使用命令mount將該文件系統安裝到主文件系統中。命令mount有三個主要參數:
◆須要安裝的文件系統類型,用「-t fstype」選項來指定,這與mkfs中的-t選項是同樣的。
◆所需訪問的文件系統所在分區名,一般是位於目錄/dev中的特別設備文件;若是須要安裝網絡文件系統時,就使用該服務器上輸出的目錄名。
◆ 安裝新文件系統的路徑名,也就是放置新文件系統的安裝點(Mount Point)。一般這是一個空目錄名,而且是專門爲安裝新文件系統而準備的。在Linux系統下,目錄/mnt是經常使用的文件系統安裝目錄,缺省狀況下, CDROM和軟盤驅動器都分別安裝在其子目錄下。固然,文件系統也能夠被安裝到其它空目錄中。例如,須要將MSDOS文件系統分區/dev/hda1安裝 到系統的空目錄/dos中,應該使用如下命令:
# mount -t msdos /dev/hda1 /dos
3.卸載文件系統
在關閉系統以前,爲了保證文件系統的完整性,全部安裝的文件系統都必須被卸載。一般在/etc/fstab文件中定義的文件系統都可以自動卸載。可是,對於手工mount的文件系統,在關閉系統以前必須手工卸載。有時候也須要在系統工做過程當中手工卸載某個文件系統。手工卸載文件系統必須使用umount命令,umount命令將分區名或分區的安裝點做爲參數,格式以下:
umount <</font>分區名或分區的安裝點>
例如,須要將已經安裝到/mnt/floppy目錄下的軟盤卸載,可使用如下命令:
# umount /mnt/floppy
要注意,對於正在使用的文件系統,不能使用umount命令卸載。
本講咱們介紹了有關Linux系統中經常使用命令格式、文件和目錄的概念、文件類型、目錄結構、文件的存取權限、文件系統的概念及其安裝命令等。有關文件操做的命令不少,讀者能夠經過上機學習各類命令的使用方法,掌握其基本功能。(T111)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
文件權限通常可認爲是0 123 456 789,一共十位:
0:表示該文件的文件類型。Windows裏面是使用了一種文件關聯的技術,經過擴展名來關聯相應的應用程序,使得雙擊某個文件,就能達到調用相應的應用程序來打開它的目的,這樣簡單快捷。然而對於用戶來講,好處是方便,壞處是隱藏了一個實質性的東西:文件的真正的類型,與其擴展名其實是毫無關聯的。
舉例來講:一個純粹的文本文件,我能夠給它命名「個人歌聲裏.mp3」,而後在win下雙擊,會調用相應的音樂播放器來打開,結果顯而易見,確定是錯誤的。那反過來,一個真正的MP3文件我也能夠給它命名「花名冊.txt」,在win下雙擊,通常會調用相應的文本編輯器來打開,不過我說你也知道,顯示的必定是亂碼。
上面兩個例子是爲了說明一個觀點,某個文件真正的類型與其擴展名沒一毛錢關係。
那麼在不知道文件擴展名的狀況下,如何知道文件的類型呢?在Linux是這樣的。
Linux中文件類型只有如下這幾種:
1.-,普通文件。
2.d,目錄文件,d是directory的簡寫。
3.l,軟鏈接文件,亦稱符號連接文件,s是soft或者symbolic的簡寫。
4.b,塊文件,是設備文件的一種(還有另外一種),b是block的簡寫。
5.c,字符文件,也是設備文件的一種(這就是第二種),c是character的文件。
Linux系統最原始的也只有這五種,因此第0位,只能是以上五者之一。
那麼你會有疑問,
1.MP3文件是是哪一種?答案:普通文件。
2.二進制文件是哪一種?答案:普通文件。
3.文本文件是哪一種?答案:普通文件。
4.爲何硬鏈接沒有類型表示?答案:硬鏈接和軟鏈接,名字上雖然只差一個字,本質徹底不一樣,硬鏈接也是文件。其類型是普通文件。
爲何上面要說這麼多呢?目的是爲下文作知識鋪墊。
那麼 123-456-789 都好說,瞭解這塊兒的人都知道,他們只是 【用戶-屬組-其餘 】這三組之間的區別,咱們拿其中任意一組做爲例子來說解rwx皆可。
r:read,w:write,x:execute。
咱們應該如何去記憶這二者之間的區別呢??難道死記硬背?NO。
咱們應該知其然還得知其因此然,下面我試圖從這查詢文件以及內容的本質出發,來闡述rwx權限在這二者身上爲什麼有不一樣的意義!
理解下面的所說的,須要關於Linux的文件系統的知識作鋪墊。若是不知道inode這個概念,基本上就會很吃虧了。
再次強調,文件的內容和該文件當時所用的文件名毫無關聯;該文件的類型,也與該文件當時的文件名,毫無關係。
查看一個文件的內容,其實是這樣的一個過程:
舉例來講,你用了這個命令:cat /tmp/abc.txt
1.你只傳遞了一個絕對路徑,/tmp/abc.txt,系統首先要知道/tmp/abc.txt文件的inode是多少才行,如何得知呢?
2.記住一個規律,某文件的父目錄會(記錄)知道該文件的inode號!(此刻我想你是否是悟出一點什麼了,不用急,接着往下看)
3.那麼我獲得「/tmp/abc.txt」這個文件名,我得先知道/tmp目錄的狀況,要知道/tmp目錄的狀況,我得先知道/目錄的狀況,因此我就能夠從/目錄開始(假設/目錄的inode號是0,而且這是【寫死的】),而後再去一張叫作inode-table的表中查找inode號0所指向的數據域,而後從數據域裏面能夠找到一些相似於下面的內容:(看起來像一張表,不是麼?其實能夠想象到,目錄文件就是一張表,存儲了它內部有哪些【文件名】,以及該文件名對應的inode號)
文件名 inode號
bin 18
var 19
tmp 20
... ...
好了,咱們從「/」,這個目錄文件中找到了「/tmp」【文件名】對應的inode號,就是20。(假設啊)
4.而後咱們經過inode號20,去inode-table裏面找尋20對應的數據域,而後從數據域中,咱們又會找到一張表:(爲何又是表呢?由於「/」是一個目錄,「/tmp」也是一個目錄,那固然數據域裏面存的仍是表啦)
文件名 inode號
abc.txt 8899
bbb.mp3 10088
kkk.jpg 20000
... ...
好了,咱們找到了/tmp/abc.txt的inode號了,就是8899。根據上面的規律,咱們是否是又得去inode-table裏面找8899號對應的數據域了?對,就是這樣。
5.咱們找到inode號8899對應的數據域,因而咱們會發現以下一些內容:
「abcdefg」(假設文件內容就是這樣)
...
又有疑問了,爲毛此次不是表了?
答案:/tmp/abc.txt文件【不是目錄文件】了,它【是一個普通文件,他存儲的通常都是一些字符串】。
體如今本質上:
普通文件:存儲普通數據,通常就是字符串。
目錄文件:存儲了一張表,該表就是該目錄文件下,全部文件名和inode的映射關係。
從父目錄中得到本文件的inode號---->找到inode-table表中找到這個inode號對應的數據域中的起點以及其餘信息---->去這個數據域中讀取該文件的內容(普通文件的內容通常是字符串,目錄文件的內容是一張表)
若是你真心看懂上面我說的了,那麼接下來就變得簡單多了。
關鍵就是訪問任何一個文件,要看是否能搞到inode號,搞不到就沒轍了。搞到inode就好說了,拿着inode號去inode表中查找便可,最後找到數據域,那麼就能夠找到文件的內容了
而後整個過程這不只僅跟本文件權限有關,還跟它的父目錄(還有父目錄的父目錄...)權限有關(是否能搞到本文件的inode)
體如今命令上:(話說這纔是最實際的表象)
======
對於普通文件來講,rwx的意義是:
r:能夠得到這個普通文件的名字和內容。
w:能夠修改這個文件的內容和文件名。能夠刪除該文件,可是用戶會獲得是否刪除寫保護文件的prompt。
x:該文件是否具備被執行的權限。
======
對於目錄文件來講,rwx的意義是:
r-x:能夠進入cd該目錄,能夠得到該目錄下存儲狀況,可是不能修改這個目錄內部存儲的文件(目錄)的名字,也不能在該目錄下新建文件和目錄
-wx:能夠進入cd該目錄,可是看不到該目錄下的存儲狀況(ls不可用),能夠往該目錄下添加、修改、刪除文件。能夠經過cat來讀取該目錄下的文件or目錄的內容,因爲得不到該目錄下存儲了那些文件,在不知情的狀況下只能經過猜,cat + 【文件名】得到文件內容,因此這樣依然不保密。
--x:能夠進入cd該目錄,看不到存儲狀況,也不能往該目錄下添加、修改、刪除文件。可是依然能夠經過cat + xx(猜)來得到該目錄下的文件的內容。
rw-:不能進入cd該目錄,用ls僅僅能夠得到文件名和目錄名,由於獲取不到這些文件的inode號,固然也不能得到該目錄下的文件的內容。不能往該目錄下添加、修改、刪除文件。
======
最後總結一下吧:
1.目錄文件雖然是文件(唉,誰叫Linux的核心理念就是Everything is file),可是存儲內容的只是一張表而已,關於文件名和inode號的映射關係。
2.文件的擴展名和文件類型之間,沒一毛錢關係。
3.文件的文件名和文件實際存儲內容之間,沒一毛錢關係,只是做爲用戶的一種識別標記。
4.要知道如何查找到一個文件內容的過程。
5.爲何同一個文件系統移動文件要比跨文件系統快?
答:由於只須要修改某個目錄中路徑和inode對應關係便可,不須要從新寫一遍數據域。
6.什麼是買來的500G的硬盤,格式化完後老是少了達不到500G?
答:從本文可知,inode-table也是須要佔用存儲空間的,因此缺乏的一部分中inode-table佔用了很多。
7.我不想吃虧,那麼我要如何瞭解Linux文件系統和inode的相關知識,可否推薦個文章?
答:http://www.cyberciti.biz/tips/understanding-unixlinux-filesystem-inodes.html
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
![](http://static.javashuo.com/static/loading.gif)
3.2.1.一、普通文件(- regular file)
(1)文本文件。文件中的內容是由文本構成的,文本指的是ASCII碼字符。文件裏的內容本質上都是數字(無論什麼文件內容本質上都是數字,由於計算機中自己就只有1和0),而文本文件中的數字自己應該被理解爲這個數字對應的ASCII碼。常見的.c文件, .h文件 .txt文件等都是文本文件。文本文件的好處就是能夠被人輕鬆讀懂和編寫。因此說文本文件天生就是爲人類發明的。
(2)二進制文件。二進制文件中存儲的本質上也是數字,只不過這些數字並非文字的編碼數字,而是就是真正的數字。常見的可執行程序文件(gcc編譯生成的a.out,arm-linux-gcc編譯鏈接生成的.bin)都是二進制文件。
(3)對比:從本質上來看(就是刨除文件屬性和內容的理解)文本文件和二進制文件並無任何區別。都是一個文件裏面存放了數字。區別是理解方式不一樣,若是把這些數字就看成數字處理則就是二進制文件,若是把這些數字按照某種編碼格式去解碼成文本字符,則就是文本文件。
(4)咱們如何知道一個文件是普通文本文件仍是二進制文件?在linux系統層面是不區分這兩個的(譬如以前學過的open、read、write等方法操做文件文件和二進制文件時一點區別都沒有),因此咱們沒法從文件自己準確知道文件屬於哪一種,咱們只能原本就知道這個文件的類型而後用這種類型的用法去用他。有時候會用一些【後綴名】來人爲的標記文件的類型。
(5)使用文本文件時,常規用法就是用文本文件編輯器去打開它、編輯它。常見的文本文件編輯器如vim、gedit、notepad++、SourceInsight等,咱們用這些文本文件編輯器去打開文件的時候,編輯器會read讀出文件二進制數字內容,而後按照編碼格式去解碼將其還原成文字展示給咱們。若是用文本文件編輯器去打開一個二進制文件會如何?這時候編輯器就覺得這個二進制文件仍是文本文件而後試圖去將其解碼成文字,可是解碼過程不少數字並不對應有意義的文字因此成了亂碼。
(6)反過來用二進制閱讀工具去讀取文本文件會怎麼樣?得出的就是文本文字所對應的二進制的編碼。
3.2.1.二、目錄文件(d directory)就是目錄裏的文件。
(1)目錄就是文件夾,文件夾在linux中也是一種文件,不過是特殊文件。用ls打開一個文件夾就能看到,文件夾其實也是一種特殊文件,裏面存的內容包括這個文件的路徑,還有文件夾裏面的文件列表。
(2)可是文件夾這種文件比較特殊,自己並不適合用普通的方式來讀寫。linux中是使用特殊的一些API來專門【讀寫文件夾】的。
(3)目錄文件和文件目錄有什麼區別?
好比你有1 2 3三個圖片文件存放在E:\psd裏。
「1」「2」「3」這三個文件就是「E:\psd」這個目錄裏的文件,「目錄文件」指的是「1 2 3」這三個文件。 「E:\psd」是「1 2 3」這三個文件所在的目錄,「文件目錄」指的是「E:\psd」這個目錄。 不一樣的就是「目錄文件」指的是某些「文件」,「目錄」只是定義這些文件存放的位置。 「文件目錄」指的是某個目錄,「文件」只是定義這個目錄裏具備哪些文件。 前者定義的是「文件」後者定義的是「目錄」
3.2.1.三、字符設備文件(c character)
3.2.1.四、塊設備文件(b block)
(1)設備文件對應的是硬件設備,也就是說這個文件雖然在文件系統中存在,可是並非真正存在於硬盤上的一個文件,而是文件系統虛擬製造出來的(叫虛擬文件系統,如/dev /sys /proc等)
(2)虛擬文件系統中的文件大多數不能或者說不用直接讀寫的,而是用一些特殊的API產生或者使用的,具體在驅動階段會詳解。
3.2.1.五、管道文件(p pipe)
3.2.1.六、套接字文件(s socket):這種文件類型用於進程間的網絡通訊
3.2.1.七、符號連接文件(l link):這種文件類型指向另外一個文件
【普通文件是一個"-",目錄文件是一個"d"標識。字符設備文件是"c",塊設備文件"b",管道文件「p」,套接字文件「S」,符號連接文件「l」。 】
3.2.2.經常使用文件屬性獲取
3.2.2.一、stat、fstat、lstat函數簡介
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf); //帶有const的是輸入型參數,查看一個未打開的文件屬性
int fstat(int fd, struct stat *buf); //查看一個已經打開的文件屬性
int lstat(const char *path, struct stat *buf); //查閱的是符號連接文件自己的屬性。
(1)每一個文件中都附帶了這個文件的一些屬性(屬性信息是存在於文件自己中的,可是它不像文件的內容同樣能夠被vi打開看到,屬性信息只能被專用的API打開看到)
(2)【文件屬性信息】查看的API有三個:stat、fstat、lstat,三個做用同樣,參數不一樣,細節略有不一樣。
(3)linux命令行下還能夠去用stat命令去查看文件屬性信息,實際上stat命令內部就是使用【stat系統調用】來實現的。
(4)
【int stat(const char *path, struct stat *buf); //帶有const的是輸入型參數
stat這個API的做用就是讓內核將咱們要查找屬性的文件的屬性信息結構體的值放入咱們傳遞給stat函數的buf中,當stat這個API調用從內核返回的時候buf中就被填充了文件的正確的屬性信息,而後咱們經過查看buf這種結構體變量的元素就能夠得知這個文件的各類屬性了。
(5)fstat和stat的區別是:stat是從文件名出發獲得文件屬性信息結構體(命令使用時,直接就是stat FILENAME),而fstat是從一個已經打開的文件fd出發獲得一個文件的屬性信息。因此用的時候若是文件沒有打開(咱們並不想打開文件操做而只是但願獲得文件屬性)那就用stat,若是文件已經被打開了而後要屬性那就用fstat效率會更高(stat是從磁盤去讀取文件的,而fstat是從內存讀取動態文件的)。
(6)lstat和stat/fstat的差異在於:對於符號連接文件,stat和fstat查閱的是【符號連接文件指向的那個文件的屬性】,而lstat查閱的是符號連接文件自己的屬性。
3.2.2.二、struct stat結構體簡介 【 man 2 stat 】
(1)struct stat是內核定義的一個結構體,在<sys/stat.h>中聲明,因此咱們能夠用。這個結構體中的全部元素加起來就是咱們的【文件屬性信息】。
int stat(const char *path, struct stat *buf); //帶有const的是輸入型參數,後面是一個結構體指針
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection 查看一個文件的權限信息*/
nlink_t st_nlink; /* number of hard links */ 硬鏈接號碼
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes 總共大小*/
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
一個文件1.file_shuxing_test1.c的屬性信息:
File: ‘1.file_shuxing_test1.c’
Size: 173 Blocks: 1 IO Block: 1024 regular file
Device: 18h/24d Inode: 66 Links: 1
Access: (0777/-rwxrwxrwx) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2016-04-11 02:03:14.242978200 +0000
Modify: 2016-04-11 03:03:35.280089700 +0000
Change: 2016-04-11 03:03:35.280089700 +0000
Birth: -
3.2.2.三、寫個程序來查看一些常見屬性信息
代碼以下:
int stat(const char *path, struct stat *buf); //帶有const的是輸入型參數,後面是一個結構體指針
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NAME "1.txt"
int main(void)
{
int ret = -1;
struct stat buf; //定義一個結構體buf變量,buf只是個變量名而已,我也能夠定義成其餘名字
memset(&buf, 0, sizeof(buf)); // memset後buf中全是0
ret = stat(NAME, &buf); // stat後buf中有內容了
if (ret < 0)
{
perror("stat");
exit(-1);
}
// 成功獲取了stat結構體,從中能夠獲得各類屬性信息了
printf("inode = %d.\n", buf.st_ino);
printf("size = %d bytes.\n", buf.st_size);
printf("st_blksize = %d.\n", buf.st_blksize);
return 0;
}
3.2.3.stat函數的應用案例
stat結構體
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
3.2.3.一、用代碼判斷文件類型
(1)文件類型就是-、d、l····
(2)文件屬性中的文件類型標誌在struct stat結構體的mode_t st_mode元素中,這個元素實際上是一個按位來定義的一個位標誌(有點相似於ARM CPU的CPSR寄存器的模式位定義)。這個東西有不少個標誌位共同構成,記錄了不少信息,若是要查找文件權限功能時按位&操做就知道結果了,可是由於這些位定義不容易記住,所以linux系統給你們事先定義好了不少宏來進行相應操做,咱們【只要把stat結構體中的mode_t st_mode元素做爲參數傳給這些宏中】,根據宏的返回值就能夠判斷文件類型等。
/*
linux系統給你們事先定義好了不少宏:咱們把mode_t st_mode元素做爲參數傳給這些宏中
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.) //是否是一個符號連接文件
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
*/
(3)譬如S_ISREG宏返回值是1表示這個文件是一個普通文件,若是文件不是普通文件則返回值是0.
3.2.3.二、用代碼判斷文件權限設置
(1)st_mode中除了記錄了文件類型以外,還記錄了一個重要信息:文件權限。
(2)linux並無給文件權限測試提供宏操做,而只是提供了【位掩碼】,因此咱們只能用位掩碼來本身判斷是否具備相應權限。
/*
位掩碼
S_IFMT 0170000 bit mask for the file type bit fields
S_IFSOCK 0140000 socket
S_IFLNK 0120000 symbolic link
S_IFREG 0100000 regular file
S_IFBLK 0060000 block device
S_IFDIR 0040000 directory
S_IFCHR 0020000 character device
S_IFIFO 0010000 FIFO
S_ISUID 0004000 set-user-ID bit
S_ISGID 0002000 set-group-ID bit (see below)
S_ISVTX 0001000 sticky bit (see below)
S_IRWXU 00700 mask for file owner permissions
S_IRUSR 00400 owner has read permission
S_IWUSR 00200 owner has write permission
S_IXUSR 00100 owner has execute permission
S_IRWXG 00070 mask for group permissions
S_IRGRP 00040 group has read permission
S_IWGRP 00020 group has write permission
S_IXGRP 00010 group has execute permission
S_IRWXO 00007 mask for permissions for others (not in group)
S_IROTH 00004 others have read permission
S_IWOTH 00002 others have write permission
S_IXOTH 00001 others have execute permission
*/
代碼測試:
/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define NAME "1.txt"
int main(void)
{
int ret = -1;
struct stat buf;
memset(&buf, 0, sizeof(buf)); // memset後buf中全是0
ret = stat(NAME, &buf); // stat後buf中有內容了
if (ret < 0)
{
perror("stat");
exit(-1);
}
#if 0
// 判斷這個文件屬性
//int result = S_ISREG(buf.st_mode);
int result = S_ISDIR(buf.st_mode);
printf("result = %d\n", result);
#endif
// 文件權限測試
//unsigned int result = (buf.st_mode & S_IRWXU) >> 8;
unsigned int result = ((buf.st_mode & S_IRUSR)? 1: 0);
printf("file owner: %u.\n", result);
return 0;
}
*/
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.4.文件權限管理1
3.2.4.一、st_mode中記錄的文件權限位
(1)st_mode本質上是一個32位的二進制數(類型就是unsinged int),這個數裏的每個位表示一個含義。
(2)【文件類型和文件的權限】都記錄在st_mode中。咱們查找文件的權限的時候使用專門的掩碼去取出相應的位便可得知相應的信息。
3.2.4.二、ls -l打印出的權限列表
(1)
123456789一共9位,3個一組。第一組三個表示文件的屬主(owner、user)對該文件的可讀、可寫、可執行權限;第2組3個位表示文件的屬主所在的組(group)對該文件的權限;第3組3個位表示其餘用戶(others其餘組裏的用戶)對該文件的權限。
(2)屬主就是這個文件屬於誰,通常來講文件建立時屬主就是建立這個文件的那個用戶。可是咱們一個文件建立以後還能夠用chown命令去修改一個文件的屬主,還能夠用chgrp命令去修改一個文件所在的組。
3.2.4.三、文件操做時的權限檢查規則
(1)一個程序a.out被執行,a.out中試圖去操做一個文件1.txt,這時候如何斷定a.out是否具備對1.txt的某種操做權限呢?
(2)斷定方法是:首先1.txt具備9個權限位,規定了3種人(user、group、others)對該文件的操做權限。因此咱們斷定1.txt是否能被a.out來操做,關鍵先搞清楚a.out對1.txt到底算哪一種人。準確的說是看a.out被誰執行,也就是當前程序(進程)是哪一個用戶的進程。
(3)剛纔上面說的是個人分析,到底對不對還得驗證。
代碼:
/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define NAME "1.txt"
int main(void)
{
int ret = -1;
ret = open(NAME, O_RDONLY);
if (ret > 0)
{
printf("可讀 ");
close(ret);
}
else
{
perror("read");
}
ret = open(NAME, O_WRONLY);
if (ret > 0)
{
printf("可寫 ");
close(ret);
}
else
perror("write");
return 0;
}
*/
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.5.文件權限管理2
3.2.5.一、access函數檢查權限設置 man 2 access [R_OK W_OK X_OK F_OK] 返回值爲0或-1
【 R_OK, W_OK, and X_OK test whether the file exists and grants read, write, and execute permissions, respectively.】
【The check is done using the calling process's real UID and GID】
【 On success (all requested permissions granted, or mode is F_OK and the file exists), zero is returned. On error (at least one bit in mode asked for a permission that is denied, or mode is F_OK and the file does not exist, or some other error occurred), -1 is returned, and errno is set appropriately.】
【】
(1)文本權限管控其實蠻複雜,通常很難肯定對一個文件是否具備某種權限(由於不但跟文件自己有關係,還與誰執行這個文件有關係)。設計優秀的軟件應該是:在操做某個文件以前先判斷當前是否有權限作這個操做,若是有再作若是沒有則提供錯誤信息給用戶。
(2)access函數能夠測試獲得當前執行程序的那個用戶在當前那個環境下對目標文件是否具備某種操做權限。
【 int access(const char *pathname, int mode);】
代碼測試:
/*
#include <stdio.h>
#include <unistd.h>
#define NAME "3.txt"
int main(void)
{
int ret = -1;
ret = access(NAME, F_OK);
if (ret < 0)
{
printf("文件不存在 \n");
return -1;
}
else
{
printf("文件存在 ");
}
ret = access(NAME, R_OK);
if (ret < 0)
{
printf("不可讀 ");
}
else
{
printf("可讀 ");
}
ret = access(NAME, W_OK);
if (ret < 0)
{
printf("不可寫 ");
}
else
{
printf("可寫 ");
}
ret = access(NAME, X_OK);
if (ret < 0)
{
printf("不可執行 \n");
}
else
{
printf("可執行 \n");
}
return 0;
}
*/
3.2.5.二、chmod/fchmod與權限修改
(1)chmod是一個linux命令,用來修改文件的各類權限屬性。chmod命令【只有root用戶】纔有權利去執行修改,一種安全機制。
(2)chmod命令其實內部是用linux的一個叫【chmod的API】實現的。
fchmod是對一個已經打開的文件進行操做的。
/* man 2 chmod
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
*/
代碼:
/*
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int ret = -1;
if (argc != 2) // ./a.out test.c
{
printf("usage: %s filename\n", argv[0]);
return -1;
}
ret = chmod(argv[1], S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWOTH);
if (ret < 0)
{
perror("chmod");
return -1;
}
return 0;
}
*/
【可讀 4 可寫2 可執行1 chmod 777 最高權限 XXX用戶、組、其餘組】
3.2.5.三、chown/fchown/lchown與屬主修改
(1)linux中有個chown命令來修改文件屬主
(2)chown命令是用chown API實現的
(3)chgrp是修改組的
補充:
$ chmod u+x file 給file的屬主增長執行權限
$ chmod 751 file 給file的屬主分配讀、寫、執行(7)的權限,給file的所在組分配讀、執行(5)的權限,給其餘用戶分配執行(1)的權限
$ chmod u=rwx,g=rx,o=x file 上例的另外一種形式
$ chmod =r file 爲全部用戶分配讀權限
$ chmod 444 file 同上例
$ chmod a-wx,a+r file 同上例
$ chmod -R u+r directory 遞歸地給directory目錄下全部文件和子目錄的屬主分配讀的權限
$ chmod 4755 設置用ID,給屬主分配讀、寫和執行權限,給組和其餘用戶分配讀、執行的權限。
3.2.5.四、umask與文件權限掩碼
(1)文件掩碼【是linux系統中維護的一個全局設置】,umask的做用是用來設定咱們系統中新建立的文件的默認權限的。
(2)umask命令就是用umask API實現的
-----------------------------------------------------------------------------------------------------------------------------------------------------------
3.2.6.讀取目錄文件(目錄文件就是一個特殊的文件)
3.2.6.一、opendir與readdir函數API來打開和讀取一個目錄文件
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name); //文件指針
DIR *fdopendir(int fd);
【#include <dirent.h>
struct dirent *readdir(DIR *dirp); //結構體指針,DIR *dirp是一個目錄
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);】
(1)opendir打開一個目錄後獲得一個DIR類型的【指針】給readdir使用
(2)readdir函數調用一次就會返回一個struct dirent類型的結構體 指針,這個指針指向一個struct dirent類型的結構體變量,這個結構體變量裏面記錄了一個目錄項(所謂目錄項就是目錄中的一個子文件)。 【man 3 readdir】
/*
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* not an offset; see NOTES */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported 文件夾類型
by all filesystem types */
char d_name[256]; /* filename */
};
*/
(3)readdir調用一次只能讀出一個目錄項,要想讀出目錄中全部的目錄項必須【屢次調用readdir函數】。readdir函數內部會記住【哪一個目錄項已經被讀過了哪一個還沒讀】,因此屢次調用後不會重複返回已經返回過的目錄項。當readdir函數返回NULL時就表示目錄中全部的目錄項已經讀完了。
3.2.6.二、dirent結構體
比較重要的就是【type和name】兩個選項。
3.2.6.三、讀取目錄實戰演練
代碼示例:
#include<stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
//DIR *opendir(const char *name); //文件指針
//struct dirent *readdir(DIR *dirp);
#define NAME "./4.進程"
void main()
{
struct dirent *p1;
DIR *p=NULL;
p=opendir(NAME);
if(p==NULL)
{
perror("opendir");
_exit(-1);
}
while ((p1 = readdir(p)) != NULL)
{
printf("%s\n", p1->d_name); //打印出該目錄下的全部內容
printf("%d\n", p1->d_ino); //打印出該目錄下全部文件的inode號
//printf("%c\n", p1->d_type); //打印出該目錄下全部文件的類型
if (p1->d_type == DT_REG) //判斷文件類型This is a regular file.
{
printf("是普通文件\n");
}
else
{
printf("不是普通文件\n");
}
}
}
3.2.6.四、可重入函數介紹
(1)有些函數是可重入的有些是不可重入的,具體概念能夠去百度。
可重入函數:指一個能夠被多個任務調用的函數,這種函數在不一樣的任務調用的時候不會改變或者影響其餘任務調用該函數時的數據,這種是安全的設計架構。
(2)readdir函數和咱們前面接觸的一些函數是不一樣的,首先readdir函數直接返回了一個【結構體變量指針,這個指針指向一個結構體,這個結構體中包含了該目錄下文件的類型及名稱等內容】,由於readdir內部申請了內存而且給咱們返回了地址。屢次調用readdir其實readir內部並不會重複申請內存而是使用第一次調用readdir時分配的那個內存。【這個設計方法是readdir不可重入的關鍵。】
(3)readdir在屢次調用時【是有關聯】的,這個關聯也標明readdir函數是不可重入的。
(4)庫函數中有一些函數當年剛開始提供時都是不可重入的,後來意識到這種方式不安全,因此從新封裝了C庫,提供了對應的可重複版本(通常是不可重入版本函數名_r)
代碼:
/*
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main(int argc, char **argv)
{
DIR *pDir = NULL; //指向一個目錄文件opendir
struct dirent * pEnt = NULL; //readdir返回的結構體指針
unsigned int cnt = 0; //計算文件夾下有多少個文件
if (argc != 2)
{
printf("usage: %s dirname\n", argv[0]);
return -1;
}
pDir = opendir(argv[1]);
if (NULL == pDir)
{
perror("opendir");
return -1;
}
while (1)
{
pEnt = readdir(pDir); //readdir函數返回的一個結構體指針,這個指針指向一個存放目錄下文件(子文件)的結構體
if(pEnt != NULL) //當pEnt == NULL時,表示已經讀取完畢
{
// 還有子文件,在此處理子文件
printf("name:[%s] ,", pEnt->d_name);
cnt++;
if (pEnt->d_type == DT_REG) //判斷文件類型This is a regular file.
{
printf("是普通文件\n");
}
else
{
printf("不是普通文件\n");
}
}
else
{
break;
}
};
printf("總文件數爲:%d\n", cnt);
return 0;
}
*/
root@ubuntu:/mnt/hgfs/Winshare/1.Linux應用編程和網絡編程/2.file_shuxing# ./a.out ../1.file_io/
name:[.] ,不是普通文件
name:[..] ,不是普通文件
name:[1.txt] ,是普通文件
name:[a.out] ,是普通文件
name:[file1.c] ,是普通文件
name:[test.txt] ,是普通文件
總文件數爲:6