C 程式設計/POSIX 參考/sys/stat.h/stat
stat() 是一個 Unix 系統呼叫,它返回有關檔案 inode 的有用資料。stat() 的語義在不同的 作業系統 之間有所不同。例如,Unix 命令 ls 使用它來檢索有關(除許多其他資訊外)的資訊
- mtime: 時間 最後修改(
ls -l), - ctime: 最後狀態更改時間(
ls -lc)和 - atime: 最後訪問時間(
ls -lu)。
在所有符合 POSIX 標準的 類 Unix 作業系統上都可以找到的 POSIX 庫標頭檔案 sys/stat.h 聲明瞭 stat()、fstat() 和 lstat() 例程
int stat(const char *filename, struct stat *buf);
int lstat(const char *filename, struct stat *buf);
int fstat(int filedesc, struct stat *buf);
並定義了 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 */
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 */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
lstat() 是一個 庫函式,它檢索 檔案 的狀態。它與 stat() 相同,不同之處在於當檔案是 符號連結 時,它返回有關連結本身的資訊,而不是連結到的檔案的資訊。
fstat() 是一個 庫函式,它檢索檔案的狀態。它與 stat() 相同,不同之處在於檔案的標識作為 檔案描述符 而不是作為 檔名 傳遞。
寫入檔案會更改其 mtime 和 ctime,而讀取檔案會更改其 atime。因此,在符合 POSIX 標準的系統上,讀取檔案會導致寫入,這一點受到了批評。這種行為通常可以透過在 /etc/fstab 中新增一個掛載選項來停用。
但是,關閉 atime 更新會破壞 POSIX 相容性,並且一些應用程式(尤其是 mutt 郵件閱讀器(在某些配置中)和一些檔案使用監視工具,尤其是 tmpwatch)也會因此而無法正常工作。在最壞的情況下,不更新 atime 會導致某些備份程式無法備份檔案。
Linux 核心開發人員 Ingo Molnár 將 atime 稱為“可能是歷史上最愚蠢的 Unix 設計理念”,[1][2] 並補充道:“想一想:‘對於從磁碟讀取的每個檔案,讓我們執行...寫入磁碟!並且,對於已經快取並從快取中讀取的每個檔案...執行寫入磁碟!’”他還強調了這種效能影響
- Atime 更新是 Linux 今天面臨的最大的 IO 效能缺陷。擺脫 atime 更新將比過去 10 年所有頁面快取加速的總和,_加在一起_,為我們帶來更多日常的 Linux 效能。
當前版本的 Linux、Mac OS X、Solaris、FreeBSD、NetBSD 和 OpenBSD 支援 noatime 掛載選項,該選項會導致 atime 欄位永遠不會被更新。這會破壞與 POSIX 的相容性。
當前版本的 Linux 支援四個掛載選項,可以在 fstab 中指定
strictatime(以前是 atime,以前是預設值;從 2.6.30 開始是 strictatime)– 始終更新 atime。relatime–(相對 atime),在 2.6.20 中引入,從 2.6.30 開始是預設值nodiratime– 永遠不要更新目錄的 atimenoatime– 永遠不要更新 atime;包括 nodiratime;最高效能,最低相容性
strictatime 符合 POSIX 標準;Alan Cox 將其他選擇描述為
- 關閉 atime,它與標準不相容,切換到 relatime,它與標準不相容,但不會破壞任何東西(這很好)
使用 noatime 選項掛載的檔案系統不會在讀取時更新 atime,而 relatime 選項僅在先前 atime 早於 mtime 或 ctime 或者先前 atime 超過 24 小時之前時才會更新 atime。許多使用者使用 noatime 沒有任何問題,只要他們不使用依賴 atime 的應用程式,並且這比 relatime 提供了一些好處(讀取時永遠不會寫入 atime)。
從 2.6.30(2009 年 6 月 9 日)開始,Linux 預設使用 relatime,[3] 這樣它就不會在所有檔案讀取時更新 atime。這種行為為大多數用途提供了足夠的效能,並且不應破壞任何重要的應用程式。在做出決定之前,對檔案系統性能進行了擴充套件討論。[4] 事實上,relatime 預設是 Linux 在 2.6.29 版本釋出後應用的首個補丁。在最初的補丁中,relatime 僅在 atime < mtime 或 atime < ctime 時更新 atime;後來進行了修改,以更新 24 小時或更長時間之前的時間,以便 tmpwatch 和 Debian 的流行度計數器(popcon)能夠正常執行。
請注意,ctime 與檔案建立時間無關。它在每次檔案內容更改時(與 mtime 同時)更新,以及在元資料更改時更新,例如檔案許可權、檔案所有權以及硬連結的建立和刪除。在某些實現中,ctime 會因檔案重新命名而受到影響(原始 Unix 和現代 Linux 都傾向於這樣做)。
與 atime 和 mtime 不同,ctime 無法透過 utime() 設定(如 touch 所使用的);唯一能將其設定為任意值的方法是更改系統時鐘。
time_t 提供精確到 1 秒的時間。
某些檔案系統提供更高的粒度。在 Linux 核心 2.5.48 及以上版本中,stat 結構支援三個檔案時間戳欄位的納秒級解析度。這些以 stat 結構中的附加欄位形式公開。
FAT 檔案系統提供的 timestamps 粒度為 2 秒。[7]
- ↑ Kernel Trap: Linux: Replacing atime With relatime,由 Jeremy 於 2007 年 8 月 7 日撰寫
- ↑ Once upon atime,LWN,由 Jonathan Corbet 於 2007 年 8 月 8 日撰寫
- ↑ Linux 2 6 30,Linux 核心新手
- ↑ That massive filesystem thread,LWN,由 Jonathan Corbet 於 2009 年 3 月 31 日撰寫
- ↑ Installing Linux on USB – Part 4: noatime and relatime mount options
- ↑ Relatime Recap,Valerie Aurora
- ↑ How accurate is ruby mtime and friends at StackOverflow.com