(二)文件屬性

我們通過ls查到就是文件屬性,只不過ls只顯示了部分文件屬性

Table of Contents

1.涉及到的OS API

2.文件類型

2.1 文件的7種類型

2.2 如何判斷文件的類型 

3、獲取文件屬性的函數,stat、lstat、fstat

3.1 stat

3.2 lstat

3.3.fstat

3.5 r w x的含義

4. umask函數

4.0 open函數創建新文件時的一個問題

4.1 函數原型

4.2每一個進程都有一個文件權限掩碼

6. 文件長度st_size

7. 文件截斷函數truncate、    ftruncate

7.1 函數原型

8. 空洞文件

9. 文件系統是如何管理文件的    

文件系統管理文件的邏輯結構——樹形結構    

文件在塊設備上是如何存儲的

文件系統是如何通過“文件路徑名”索引找到文件

10. link,unlink,remove,rename函數

10.1.1 硬鏈接

10.1.2 link函數

10.2 unlink函數

10.3、remove函數

10.4、rename函數

11.1 軟鏈接文件 (快捷圖標)

11.4 符號跟隨函數 與 符號不跟隨函數

12. getcwd、chdir、mkdir、rmdir

12.1 getcwd

12.2 chdir

12.3 mkdir函數

12.4 rmdir函數

13. opendir、readdir

13.1 opendir

13.2 readdir

14. chmode、fchmod


1.涉及到的OS API

stat、fstat、lstat

umask

chmod、fchmod

chown,fchown,lchown

link,unlink,remove,ren
symlink和readlink

chdir、和getcwd


看起來很多,不過每一行都是一組,只要理解其中一個,其它的都很好理解。

而且這些函數,都與我們常用的cd、ls、chmod、chown、pwd等命令息息相關

2.文件類型

2.1 文件的7種類型

Linux一切皆文件,文件一共分爲7類分別是 - d c s p l b

(1)普通文件(regular file:-  

             文本文件           純二進制文件(機器碼)

(2)目錄文件(director file:d)

             目錄是一種特殊的文件,專門用於管理其它文件。

(3)字符設備文件(character special file:c)

             字符設備文件,就是字符設備驅動程序,在上層的表現形式。

(4)塊設備文件(block special file:b):對應塊設備(如磁盤等)。

             1)塊設備文件,是塊設備驅動程序在上層的表現形式。

             2)字符設備與塊設備有什麼區別?

                     

(5)FIFO(fifo:p)

          管道文件,用於實現不同進程(程序)之間的通信

(6)套接字文件(socket:s)

          專門用於網絡通信的文件。

(7)符號連接(symbolic link:l):

          其實就是一種快捷圖標,背後指向了另外一個文件。

2.2 如何判斷文件的類型 

(1)ls查看- d c l b s p符號來區分

(2)可以使用file命令來查看

         (a)如果查看的是文本文件

         (b)如果你查看的是純二進制文件(機器碼)

           

3、獲取文件屬性的函數,stat、lstat、fstat

ls命令其實就是調用了這三個函數中的lstat來實現的,我們可以調用lstat函數來自己實現一個ls命令。

這三個是兄弟函數,實現的功能相同,只是略微有區別,我們只要先把stat函數搞清楚了,lstat、fstat非常容易理解。

3.1 stat

函數原型

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *path, struct stat *buf);

 

3.2 struct stat結構體

7類文件都有的屬性

專門給塊設備文件用的。

專門給字符設備用的

ls的信息

(1)st_uid 和 st_gid    用戶id      組的組id

 

(2)st_mode

          (a)- :文件類型

          (b)rwxrwxr-x:文件權限   (讀寫執行)   

                       文件所屬用戶   所屬組    其他人

 

(3)將數字形式的st_mode,打印爲-rwxrwxr-x形式

          文件類型
                   12~15 bit用於表示文件類型

                    如何表示文件類型

                                     

                  · 如何取出12~15位的值,然後用於判斷文件的類型

                   

                   

       文件權限

                   

 

  (4)如何使用chmod命令修改文件權限(rwx)

          (a)方法1:直接使用數字   chmod 777 file.txt

          (a)方法2:直接使用rwx來設置

               · 例子1:修改所有權限 - chmod a=rw- file.txt 

               · 例子2:只修改某一組的權限- chmod u=rwx,g=rw-,o=r-- file.txt

               · 例子3:只修改組裏面某一位的權限- chmod u+r,g+w,o+x file.txt

3.2 lstat

3.3.fstat

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int fstat(int fd, struct stat *buf);

3.5 r w x的含義

1)x對於普通文件來說

如果普通文件存放的只是文字編碼,因爲文字編碼無法被cpu執行,所以普通文件的x沒有太大意義,所以一般的普通文件的x權限一般都是-。

2)x對於目錄的意義?

我們發現目錄都有x,顯然目錄裏面放的並不是機器指令,是不能被執行的,那麼x對於目錄的意義何在呢?

對於目錄的x來說,也被稱爲通過權限,也就是說,如果你的目錄沒有x權限,你是無法通過這個目錄的。

3)x對於其它文件來說,意義不大

4. umask函數

4.0 open函數創建新文件時的一個問題

 open函數創建新的文件時,如果指定的是0777滿級權限的話,實際創建文件權限爲0775(rwxrwxr-x) 

(1)爲什麼不是滿級權限

      因爲被文件權限掩碼做了限制。

       

(2)怎麼將文件權限掩碼改爲0

      使用umask即可。

4.1 函數原型

#include <sys/types.h>
#include <sys/stat.h>

mode_t umask(mode_t mask);

    

4.2每一個進程都有一個文件權限掩碼

我的程序,修改只是當前進程的文件權限掩碼,對其它進程的文件權限掩碼無影響。

6. 文件長度st_size

struct stat中的st_size被用來存放文件長度,但只對普通文件目錄、以及符號連接文件有意義。

因爲只有普通文件、目錄、以及符號鏈接文件纔有實際的數據,有數據纔有文件長度

其它的文件在塊設備上只存儲了文件屬性,它們只是掛了一個文件名,以文件的形式進行管理而已,沒有實際的數據,所以對於 這些文件來說,文件大小是沒有意義的。

符號鏈接文件的文件大小 

符號鏈接文件就是一個快捷鍵,背後指向了某個文件。

符號鏈接文件的數據,就是所指向文件的文件名,所以它的文件大小指的就是這個名字的字符個數。

7. 文件截斷函數truncate、    ftruncate

open可以指定了O_TRUNC後,文件裏面有數據的話,會將打開的文件截短(清空)爲0,

文件截短函數truncate,它不僅能夠將文件截爲0,還可以把文件截短爲任意長度。

7.1 函數原型

#include <unistd.h>
#include <sys/types.h>
	
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);

8. 空洞文件

我承諾給你一畝地,但是你又不是馬上就要用滿這一畝地,是一點一點來佔用的,如果我現在一下子把一畝地全部你,

但是你要花費很久時間纔會把地全用上,在你佔滿之前,一直有相當部分空間被閒置不用,顯然非常浪費空間資源。

迅雷等下載文件

比如下載一個1M大小的文件,文件肯定是要花費相當長的時間才能下載完成,如果我直接就開闢一個實際佔用1M空間
的普通文件來放數據的話,在實際下載完數據之前,未裝滿數據的空間都被閒置,會很浪費空間,怎麼辦呢?

 

解決辦法就是開闢一個1M大小的空洞文件,空洞文件的理論大小是1M,但是並沒有在塊設備上實際給你分配1M的物理空間 而是在下載過程中,每下載一部分數據,再實際開闢一部分空間給你,直到整個文件下完位置。

如何製作空洞文件

truncate、ftrucate製作

        文件截短長度 > 文件長度時,多餘的部分就是空洞。

        du命令:查看文件在塊設備上,實際佔用的物理空間。

        ls查看到的只是文件的理論大小,但是空洞部分並不佔用實際物理存儲空間。

使用lseek製作

        將文件讀寫位置調整到文件尾部之後,然後寫點數據,中間空出的部分就是空洞。

9. 文件系統是如何管理文件的    

文件系統管理文件的邏輯結構——樹形結構    

對於文件系統來說,目錄是非常重要的文件組織節點。

文件在塊設備上是如何存儲的

(1)超級區

               負責“塊設備”空間的分配和回收。

(2)inode節點區

               1)被劃分爲了一個個相連的,空間大小相同的inode節點空間。

               2)每個節點空間被用於存放某個文件的屬性信息,每個節點空間大小是固定的

               3)每個節點都有一個節點編號,通過節點編號就可以索引找到inode節點空間。

(3)數據區

           存儲數據時,實際上並不是數據有多少個字節,就分配對應多少的字節空間給你,爲了便於物理空間高效管理,往往都是按塊 分配空間的,一塊往往爲4k字節(4*1024)

       1)普通文件

       2)目錄文件

             

       3)鏈接文件 :  存放的數據很簡單,就是所指向文件的文件名。

文件系統是如何通過“文件路徑名”索引找到文件

1)索引找到普通文件 

fd = open("/new/xxx.txt", O_RDWR); 

找到數據存放空間的起始地址後,read、write調用驅動讀寫數據時, 塊設備驅動程序”通過這個地址,就能夠實現讀寫。

 

stat("/new/xxx.txt", ...); 

       這個函數獲取文件屬性時,也是按照相同的原理來索引的,找到文件的inode節點空間後,就可以將inode節點中的文件屬性讀取出來。

10. link,unlink,remove,rename函數

這幾個函數與ln、rm、mv命令息息相關,因爲這幾個命令就是調用這幾個函數來實現的

10.1.1 硬鏈接

(1)ln命令創建硬鏈接:          ln xxx.txt xxx1.txt

(2)創建硬鏈接,創建的是什麼      創建硬鏈接,就是再爲文件創建一個名字。

           1)每創建一個硬鏈接,文件就多一個文件名,硬件鏈接數+1

                

                從圖中看出,創建硬鏈接後所得到的多個文件名,指向的同一個inode節點,

                只有inode節點代表了文件的真實存在,

                inode節點只有一個,因此多個文件名指向的是同一個文件,不管使用的是哪一個文件名,都能操作這個文件。

          2)硬鏈接數

               記錄了有多少個文件名指向了inode節點,通過創建硬鏈接,每增加一個文件名,就多一個硬鏈接數。

          3)刪除文件後,文件數據還在嗎?

                還在,因爲刪除文件時,只是將文件的inode節點空間釋放了,如果這個文件有數據的話,

                那麼這個文件的數據仍然還在,只要將文件的inode節點空間恢復,即可還原該文件。

          4)有關目錄的硬鏈接數

             (a)爲什麼新建的目錄一開始的文件鏈接數就是2

                      因爲新創建的目錄,一開始就有兩個名字指向了目錄的inode節點,分別是目錄的本名new和.

                      

            (b)爲什麼在該目錄下,每多創建一個目錄,當前目錄就會多一個硬鏈數

                      新創建目錄的..名字,也指向了當前目錄new。

                      

            (c)能不能使用ln命令,自己給目錄創建硬鏈接

                      答:不能,Linux不允許用戶自己給目錄創建硬鏈接,只能由Linux系統自己給目錄創建硬鏈接。

                             用戶只能給目錄以外的,其它類型的文件創建硬鏈接。

10.1.2 link函數

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

  

10.2 unlink函數

#include <unistd.h>

int unlink(const char *pathname);

  

 

  使用unlink創建臨時文件

          所謂臨時文件就是,只在程序運行過程中有效,程序運行結束後就自動刪除,這就是臨時文件,

  如何使用unlink創建臨時文件?

  1.   open創建一個文件後(新文件的硬鏈接數都是1),然後立即調用unlink將文件硬鏈接數減爲0,將其刪除。
  2.   雖然文件的硬鏈接數變成了0,但是在進程沒有結束之前,這個文件仍然可以被使用,直到進程結束後,文件被刪

10.3、remove函數

10.3.1函數原型

#include <stdio.h>

int remove(const char *pathname);

10.3.2 爲什麼這個函數既能用於刪除一般文件,也能用於刪除目錄

(1)remove是一個庫函數  它封裝了unlink和rmdir這兩個系統函數。

          

(3)rm命令

         這個命令既能用於刪除目錄,也能用於刪除其它所有的文件,可以認爲就是調用remove實現。

10.4、rename函數

修改文件的路徑名,mv命令就是調用這個函數實現的。

函數原型

#include <stdio.h>

int rename(const char *oldpath, const char *newpath);

1)修改路徑名情況1:當只改路徑,不改文件名字 :      這種情況其實就是移動。

       如果文件移動起始位置和目標位置,在同一個分區裏面的話

  •                移動文件時,不會移動文件的數據,只是把文件的基本信息(名字、inode編號),
  •                從這個目錄記錄到另一個目錄下

       如果移動的起始位置和目標位置,不在同一個分區

  •               既要移動數據,也要移動文件基本信息

       在Linux下,分區是以目錄的形式存在的,而在windows分區是以c:等盤符形式存在

 

2)修改路徑名情況2:不改路徑,只改文件名       這種情況就是一般意義上的改名。

3)修改路徑名情況3:既改路徑,也改文件名

11. symlink、readlink

這兩個函數與符號鏈接文件有關,(軟鏈接文件)

11.1 軟鏈接文件 (快捷圖標

11.1.1 使用ln -s就可以創建符號鏈接文件

11.1.2 什麼是符號鏈接文件  

           符號鏈接文件就是一個快捷圖標,它指向了另一個文件

11.1.3 符號鏈接 與 硬鏈接的對比

       

     (1)創建硬連接

                同一個文件有多個不同的名字,它們指向是同一個inode節點。

     (2)創建符號鏈接文件

               符號鏈接文件與它所指向的文件,是兩個完全不同的獨立的文件,擁有自己獨立的inode節點。

               符號鏈接文件的數據就是指向文件的文件名,文件大小就是名字的字符個數。

     (3)不能給目錄創建硬鏈接,但是可以給目錄創建符號鏈接文

     (4)可以給符號鏈接文件,創建硬鏈接嗎  可以

#include <unistd.h>

int symlink(const char *oldpath, const char *newpath);

#include <unistd.h>

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
	

  

11.4 符號跟隨函數 與 符號不跟隨函數

(1) 符號跟隨函數

(2)符號不跟隨函數

12. getcwd、chdir、mkdir、rmdir

12.1 getcwd

這是一個庫函數,執行pwd命令就是調用這個函數實現的。

#include <unistd.h>

char *getcwd(char *buf, size_t size);

  

   pwd這個命令獲取的是,當前終端這個進程的工作路徑。

   我自己的進程調用getcwd函數,獲取的是我自己進程的當前工作路徑,默認是你運行這個程序時所在的路徑。

12.2 chdir

#include <unistd.h>
				
int chdir(const char *path);

  

12.3 mkdir函數

mkdir命令調用的就是這個函數。

#include <sys/stat.h>
#include <sys/types.h>

int mkdir(const char *pathname, mode_t mode);

12.4 rmdir函數

rmdir和rm命令刪除目錄時,調用的都是rmdir這個函數。

  •        rmdir命令:只能刪除空目錄,rmdir命令用的很少
  •        rm:不管目錄空不空,都能刪除,rm用的最多

函數原型

#include <unistd.h>

int rmdir(const char *pathname);

如果目錄不爲空,必須遞歸調用rmdir函數,實現遞歸刪除。 

什麼是遞歸刪除?

13. opendir、readdir

opendir:打開目錄,以便調用readdir讀取目錄項

readdir:讀取目錄裏面的目錄項


什麼是目錄項?

13.1 opendir

#include <sys/types.h>
#include <dirent.h>

DIR *opendir(const char *name);

  

13.2 readdir

#include <dirent.h>

struct dirent *readdir(DIR *dirp);

  

14. chmode、fchmod

 #include <sys/stat.h>

 int chmod(const char *pathname, mode_t mode);
 int fchmod(int fd, mode_t mode);

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章