檔案描述符、開啟檔案表以及inode
linux系統相關書籍中關於檔案描述符及相關內容,通常會出現一張類似這樣的圖
或者這樣的圖
第一個圖來自Michael Kerrisk的《Linux/UNIX系統程式設計手冊》,第二個圖來自《UNIX環境高階程式設計》(也就是APUE)。
文中對相關資訊做了論述並且配上了上面這樣的圖,但是我相信很多人看完以後覺得好像懂了,那麼請嘗試想一想一下幾個問題:
1.假如建立了檔案a得到了檔案描述符fa1,並且正在寫入的過程中再次開啟檔案a得到了檔案描述符fa2。這個時候通過fa2對檔案重新命名,會有什麼結果。
2.fa2對檔案重新命名後,通過fa1獲得的檔名是原來的檔名還是修改後的檔名。
3.fa1能否繼續寫入。
如果以上3個問題完全沒有疑惑,說明已經對檔案描述符及相關內容掌握的非常清楚,可以不用繼續看下去了。如果還有疑問,那麼請看下面這段程式碼
func main() {
fileOldName := "rotate.log"
fileRename := "rotate1.log"
file, _ := os.OpenFile(fileOldName, os.O_CREATE|os.O_WRONLY|os.O_APPEND, os.FileMode(0644))
fmt.Println("open file", fileOldName)
for i := 0; i < 5; i++ {
file.WriteString(fmt.Sprintf("%v line: %d\n", time.Now(), i))
}
var statOldFile syscall.Stat_t
if err := syscall.Stat(fileOldName, &statOldFile); err != nil {
panic(err)
}
fmt.Println(fileOldName, "statOldFile.Ino:", statOldFile.Ino)
err := os.Rename(fileOldName, fileRename)
if err != nil {
fmt.Println("file rename Error:", err)
}
fmt.Println("rename ", fileOldName, "->", fileRename)
var statRenamedFile syscall.Stat_t
if err := syscall.Stat(fileRename, &statRenamedFile); err != nil {
panic(err)
}
fmt.Println("fileRename", "statRenamedFile.Ino:", statRenamedFile.Ino)
fmt.Println("file.Name:", file.Name())
for i := 5; i < 10; i++ {
file.WriteString(fmt.Sprintf("%v line: %d\n", time.Now(), i))
}
fileOld, err := os.OpenFile(fileOldName, os.O_WRONLY|os.O_APPEND, os.FileMode(0644))
if nil != err {
fmt.Println(fileOldName, " open error:", err)
} else {
fmt.Println("fileOld.Name:", fileOld.Name())
}
}
執行後的輸出為
open file rotate.log
rotate.log statOldFile.Ino: 28567907
rename rotate.log -> rotate1.log
fileRename statRenamedFile.Ino: 28567907
file.Name: rotate.log
rotate.log open error: open rotate.log: no such file or directory
rotate1.log檔案中有10行記錄。
上面的程式碼首先建立了一個名為rotate.log的檔案,然後寫入了5行記錄,列印出檔案的inodeID 28567907,然後將檔案重新命名為rotate1.log,再次列印檔案的inodeID 28567907,繼續寫入5條記錄,列印檔案物件的名字,最後再次開啟檔案rotate.log,提示檔案不存在。
現在來分析一下程式的邏輯:
- 建立並開啟檔案rotate.log其inodeID為28567907,file物件中包含了一個檔案描述符姑且稱為FA1,指向一個檔案表項姑且稱為FT1,FT1指向一個V節點項。此V節點項的檔案就是inodeID為28567907的rotate.log檔案,寫入了5條記錄。
- 利用rename將檔案rotate.log重新命名為rotate1.log。實際就是開啟了一個檔案描述符FA2,指向檔案表FT2,FT2指向inodeID為28567907的V節點項,也就是前文的rotate.log,將V節點中這個檔案的檔名屬性修改為rotate1.log,檔案還是那個檔案,因此列印出來的inodeID還是那個inodeID。
- file物件再次寫入5條記錄,FA1沒變,FT1沒變,V節點中的inode沒變,僅僅只是檔名屬性變了,因此記錄依然寫入了原來那個檔案,雖然檔名已經變了。
- 列印file物件的檔名屬性,顯示是修改前的名字,因為file物件的name屬性在建立時已經賦值,即使V節點中的檔名已經修改,file物件中的name不會變。
- 再次開啟rotate.log會發現已經打不開了,因為這個檔案已經不存在了,畢竟V節點中這個檔案現在已經叫rotate1.log了。
- rotate1.log中有10行記錄,其中5行是改名前寫入的,5條是改名後寫入的。
通過這個例子,大概能明白文章開頭的兩個圖了吧。
為啥檔名叫rotate.log?因為logrotate就是重新命名後再次用原名建立新檔案繼續寫的。
更多golang示例程式碼見 https://github.com/changjixiong/goNotes
相關文章
- 表`t`的INODE結構檔案分析
- 檔案描述符
- 檔案描述符和檔案系統
- 列出檔案的inode資訊
- PostgreSQL的表檔案以及TOAST表檔案對應關係SQLAST
- Linux檔案描述符Linux
- 檔案包含之包含了Linux檔案描述符Linux
- ipynb檔案用什麼開啟 ipynb檔案怎麼開啟
- DBF檔案怎麼開啟?DBF檔案的開啟方法教程
- Linux下檔案描述符Linux
- TC中開啟檔案和寫入檔案
- 理解Linux檔案系統之 inodeLinux
- Linux--檔案描述符、檔案指標、索引節點Linux指標索引
- html檔案怎麼開啟(手機html檔案怎麼開啟)HTML
- 開啟壓縮檔案提示不能開啟此檔案怎麼辦
- 檔案開啟的格式
- 開啟.ziw格式檔案
- PHP之開啟檔案PHP
- 開啟檔案數限制
- java開啟PPT檔案Java
- CHM檔案打不開,提示"不能開啟檔案:mk@.....
- windows 檔案描述符 _open_osfhandleWindows
- linux中的檔案描述符Linux
- 使用檔案描述符恢復誤刪除的資料檔案
- Linux檔案系統iNode及stat命令Linux
- GPFS檔案系統inode數是否有限制?
- 檢視linux中檔案的inode資訊Linux
- mpp檔案用什麼軟體開啟 如何開啟mpp格式檔案
- cat開啟檔案正常vim開啟檔案中文亂碼解決方法
- step檔案用什麼軟體開啟 step檔案怎麼開啟
- JAVA語言的開啟檔案和寫入檔案Java
- dmg檔案如何開啟win10_win10怎麼開啟dmg檔案Win10
- Vagrant 開啟 smb 檔案共享
- VMware vmdk檔案開啟方法
- Xamarin Essentials教程開啟檔案
- .pdm檔案怎麼開啟
- Linux 檔案描述符和重定向Linux
- 基於檔案描述符的恢復