<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                # 文件系統,第 2 部分:文件是 inode(其他一切只是數據...) > 原文:<https://github.com/angrave/SystemProgramming/wiki/File-System%2C-Part-2%3A-Files-are-inodes> 好主意:忘記文件名:'inode'是文件。 通常將文件名視為“實際”文件。不是!而是將 inode 視為文件。 inode 保存元信息(最后訪問,所有權,大小)并指向用于保存文件內容的磁盤塊。 ## 那么......我們如何實現目錄? 目錄只是名稱到 inode 編號的映射。 POSIX 提供了一小組函數來讀取每個條目的文件名和 inode 號(見下文) 讓我們考慮一下它在實際文件系統中的樣子。從理論上講,目錄就像實際文件一樣。磁盤塊將包含 _ 目錄條目 _ 或 _dirents_ 。這意味著我們的磁盤塊看起來像這樣 | inode_num | 名稱 | | --- | --- | | 2043567 | hi.txt | ... 每個目錄條目可以是固定大小,也可以是變量 c-string。它取決于特定文件系統在較低級別實現它的方式。 ## 如何找到文件的 inode 編號? 從 shell 中,將`ls`與`-i`選項一起使用 ``` $ ls -i 12983989 dirlist.c 12984068 sandwich.c ``` 從 C,調用 stat 函數之一(下面介紹)。 ## 如何找到有關文件(或目錄)的元信息? 使用 stat 調用。例如,要找出上次訪問我的'notes.txt'文件的時間 - ```c struct stat s; stat("notes.txt", & s); printf("Last accessed %s", ctime(s.st_atime)); ``` 實際上有三個版本的`stat`; ```c int stat(const char *path, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *path, struct stat *buf); ``` 例如,如果您已經有與該文件關聯的文件描述符,則可以使用`fstat`查找有關文件的元信息 ```c FILE *file = fopen("notes.txt", "r"); int fd = fileno(file); /* Just for fun - extract the file descriptor from a C FILE struct */ struct stat s; fstat(fd, & s); printf("Last accessed %s", ctime(s.st_atime)); ``` 我們將在引入符號鏈接時討論第三個調用'lstat'。 除了訪問,創建和修改時間之外,stat 結構還包括 inode 編號,文件長度和所有者信息。 ```c 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 file system 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 */ }; ``` ## 如何列出目錄的內容? 讓我們編寫自己的'ls'版本來列出目錄的內容。 ```c #include <stdio.h> #include <dirent.h> #include <stdlib.h> int main(int argc, char **argv) { if(argc == 1) { printf("Usage: %s [directory]\n", *argv); exit(0); } struct dirent *dp; DIR *dirp = opendir(argv[1]); while ((dp = readdir(dirp)) != NULL) { puts(dp->d_name); } closedir(dirp); return 0; } ``` ## 如何讀取目錄的內容? Ans:使用 opendir readdir closedir 例如,這是一個非常簡單的'ls'實現來列出目錄的內容。 ```c #include <stdio.h> #include <dirent.h> #include <stdlib.h> int main(int argc, char **argv) { if(argc ==1) { printf("Usage: %s [directory]\n", *argv); exit(0); } struct dirent *dp; DIR *dirp = opendir(argv[1]); while ((dp = readdir(dirp)) != NULL) { printf("%s %lu\n", dp-> d_name, (unsigned long)dp-> d_ino ); } closedir(dirp); return 0; } ``` 注意:在調用 fork()之后,父級或子級(XOR)可以使用 readdir(),rewinddir()或 seekdir()。如果父項和子項都使用上述內容,則行為未定義。 ## 如何檢查文件是否在當前目錄中? 例如,要查看特定目錄是否包含文件(或文件名)'name',我們可能會編寫以下代碼。 (提示:你能發現這個錯誤嗎?) ```c int exists(char *directory, char *name) { struct dirent *dp; DIR *dirp = opendir(directory); while ((dp = readdir(dirp)) != NULL) { puts(dp->d_name); if (!strcmp(dp->d_name, name)) { return 1; /* Found */ } } closedir(dirp); return 0; /* Not Found */ } ``` 上面的代碼有一個微妙的錯誤:它泄漏了資源!如果找到匹配的文件名,那么'closedir'永遠不會被稱為早期返回的一部分。由 opendir 打開的任何文件描述符和任何分配的內存都不會被釋放。這意味著最終進程將耗盡資源,`open`或`opendir`調用將失敗。 解決方法是確保我們在每個可能的代碼路徑中釋放資源。在上面的代碼中,這意味著在`return 1`之前調用`closedir`。忘記釋放資源是一個常見的 C 編程錯誤,因為 C 語言中沒有任何支持來確保始終使用所有代碼路徑釋放資源。 ## 使用 readdir 有什么問題?例如,遞歸搜索目錄? 有兩個主要問題和一個考慮因素:`readdir`函數返回“。” (當前目錄)和“..”(父目錄)。如果要查找子目錄,則需要明確排除這些目錄。 對于許多應用程序,在遞歸搜索子目錄之前首先檢查當前目錄是合理的。這可以通過將結果存儲在鏈表中,或重置目錄結構以從頭重新開始來實現。 最后一點需要注意:`readdir`不是線程安全的!對于多線程搜索,使用`readdir_r`,它要求調用者傳入現有 dirent 結構的地址。 有關更多詳細信息,請參見 readdir 的手冊頁。 ## 如何確定目錄條目是否是目錄? Ans:使用`S_ISDIR`檢查存儲在 stat 結構中的模式位 并檢查文件是否是常規文件使用`S_ISREG`, ```c struct stat s; if (0 == stat(name, &s)) { printf("%s ", name); if (S_ISDIR( s.st_mode)) puts("is a directory"); if (S_ISREG( s.st_mode)) puts("is a regular file"); } else { perror("stat failed - are you sure I can read this file's meta data?"); } ``` ## 目錄是否也有 inode? 是!雖然更好的思考方法是,目錄(如文件)_ 是 _ 的 inode(帶有一些數據 - 目錄名和 inode 內容)。它恰好是一種特殊的 inode。 來自[維基百科](http://en.wikipedia.org/wiki/Inode): > Unix 目錄是關聯結構的列表,每個關聯結構包含一個文件名和一個 inode 編號。 請記住,inode 不包含文件名 - 只包含其他文件元數據。 ## 如何在文件系統中的兩個不同位置顯示相同的文件? 首先要記住文件名!=文件。可以將 inode 視為“文件”,將目錄視為名稱列表,每個名稱都映射到 inode 編號。其中一些 inode 可能是常規文件 inode,其他可能是目錄 inode。 如果我們已經在文件系統上有文件,我們可以使用'ln'命令創建指向同一 inode 的另一個鏈接 ``` $ ln file1.txt blip.txt ``` 但是 blip.txt _ 是 _ 同一個文件;如果我編輯 blip 我正在編輯與'file1.txt!'相同的文件我們可以通過顯示兩個文件名引用相同的 inode 來證明這一點: ``` $ ls -i file1.txt blip.txt 134235 file1.txt 134235 blip.txt ``` 這些類型的鏈接(也稱目錄條目)稱為“硬鏈接” 等效的 C 調用是`link` ```c link(const char *path1, const char *path2); link("file1.txt", "blip.txt"); ``` 為簡單起見,上述示例在同一目錄中創建了硬鏈接,但是可以在同一文件系統內的任何位置創建硬鏈接。 ## 當我`rm`(刪除)文件時會發生什么? 刪除文件(使用`rm`或`unlink`)時,將從目錄中刪除 inode 引用。但是,仍可以從其他目錄引用 inode。為了確定是否仍然需要文件的內容,每個 inode 保持一個引用計數,只要創建或銷毀新鏈接就會更新該引用計數。 ## 案例研究:備份最小化文件復制的軟件 硬鏈接的示例使用是在不同時間點有效地創建文件系統的多個檔案。歸檔區域具有特定文件的副本后,未來的歸檔可以重新使用這些歸檔文件,而不是創建重復文件。 Apple 的“Time Machine”軟件就是這樣做的。 ## 我可以創建目錄和常規文件的硬鏈接嗎? 不,是的。不是真的......其實你真的不想這樣做,是嗎? POSIX 標準說不,你可能不會! `ln`命令僅允許 root 執行此操作,并且僅當您提供`-d`選項時才允許 root。但是,即使 root 也可能無法執行此操作,因為大多數文件系統都會阻止它! 為什么? ## 文件系統的完整性假設目錄結構(我們稍后將討論的軟鏈接除外)是可從根目錄訪問的非循環樹。如果允許目錄鏈接,則強制執行或驗證此約束會變得昂貴。打破這些假設可能導致文件完整性工具無法修復文件系統。遞歸搜索可能永遠不會終止,目錄可以有多個父級,但“..”只能引用單個父級。總而言之,一個壞主意。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看