1 回答

TA貢獻1821條經(jīng)驗 獲得超5個贊
在運行時,我從命令行發(fā)出 rm mytest.log 并觀察到該程序在下次調(diào)用時不會產(chǎn)生錯誤
WriteString()
是的,這正是指定的行為。該文件也沒有被刪除。唯一rm
刪除的是文件系統(tǒng)中的特定路徑條目。單個文件可以有多個路徑,也稱為硬鏈接。
只有當(dāng)文件系統(tǒng)條目(鏈接)或文件描述符(在程序中打開的文件)對它的最后一次引用已關(guān)閉時,才會刪除實際文件。
Unix 文件模型的這種特殊行為長期用于實現(xiàn)“未命名”共享內(nèi)存,通過創(chuàng)建和打開文件,然后/dev/shm
刪除文件系統(tǒng)條目——因為這種特殊的做事方式引入了競爭條件,為了安全敏感應(yīng)用程序引入了新的系統(tǒng)調(diào)用,允許創(chuàng)建匿名內(nèi)存映射,最近 Linux 甚至獲得了在文件系統(tǒng)中創(chuàng)建文件的功能,而無需創(chuàng)建路徑條目(open
帶有O_TMPFILE
標(biāo)志)。
在較新版本的 Linux 上,您甚至可以為已使用系統(tǒng)調(diào)用刪除最后一個條目的文件重新/創(chuàng)建文件系統(tǒng)條目linkat
。
更新
問題是,如果最后一個文件系統(tǒng)條目消失了,你真的想報錯嗎?畢竟這不是一個糟糕的情況,您可以安全地寫入和讀取,沒有問題,請注意,一旦您關(guān)閉文件的最后一個文件描述符,它就會丟失。
完全有可能檢測到最后一個文件系統(tǒng)條目是否已被刪除,如果是,則中止文件操作——但是請注意,這樣的代碼可能會引入它自己的問題,例如,如果程序希望創(chuàng)建一個新的文件系統(tǒng)條目,使用 linkat 將所有內(nèi)容正確寫入文件后。
無論如何,您可以做的是fstat
-ing 文件(file.Stat
在 Go 中)并查看文件具有的硬鏈接數(shù)。如果該數(shù)字降為零,則所有文件系統(tǒng)條目都將消失。
package main
import (
? ? "fmt"
? ? "log"
? ? "os"
? ? "syscall"
? ? "time"
)
func main() {
? ? fmt.Println("Test Operation")
? ? f, err := os.OpenFile("test.txt", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
? ? if err != nil {
? ? ? ? log.Fatal(err)
? ? }
? ? for {
? ? ? ? n, err := f.WriteString("blah\n")
? ? ? ? if err != nil {
? ? ? ? ? ? log.Fatal(err)
? ? ? ? }
? ? ? ? log.Printf("wrote %d bytes\n", n)
? ? ? ? time.Sleep(2 * time.Second)
? ? ? ? stat, err := f.Stat()
? ? ? ? if err != nil{
? ? ? ? ? ? log.Fatal(err)
? ? ? ? }
? ? ? ? if sys := stat.Sys(); sys != nil {
? ? ? ? ? ? if stat, ok := sys.(*syscall.Stat_t); ok {
? ? ? ? ? ? ? ? nlink := uint64(stat.Nlink)
? ? ? ? ? ? ? ? if 0 == nlink {
? ? ? ? ? ? ? ? ? ? log.Printf("All filesystem entries to original file removed, exiting")
? ? ? ? ? ? ? ? ? ? break
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
- 1 回答
- 0 關(guān)注
- 167 瀏覽
添加回答
舉報