文件描述符与打开文件的关系
所有執行I/O操作的系統調用都以文件描述符,即一個非負整數來指代所打開的文件。文件描述符可以用來表示所有類型的已打開文件。同時,多個文件描述符可以指向同一個打開文件,因為有在不同進程中打開同一個文件的需求。
那么,系統是如何維護硬盤文件與文件描述符之間的聯系呢?
要理解具體的情況如何,需要查看由內核維護的3個數據結構:
- 進程級的文件描述符
- 系統級的打開文件表
- 文件系統的i-node表
- 控制文件描述符操作的一組標志(目前僅定義了一個,即close-on-exec標志)
- 對打開文件句柄的引用
- 當前文件偏移量(調用read()和write()時更新,或使用lseek()直接修改)
- 文件的訪問模式(如調用read()時設置的只讀模式、只寫模式等)
- 與信號驅動I/O相關的設置
- 對該文件i-node對象的引用
- 文件類型(如常規文件、套接字或FIFO)和訪問權限
- 一個指針,指向該文件所持有的的鎖的列表
- 文件的各種屬性,包括文件大小以及不同類型操作相關的時間戳
在進程A中,文件描述符1和20都指向同一個打開的文件句柄23,這可能是通過調用dup、dup2或fcntl形成的。 進程A的文件描述符2和進程B的文件描述符2都指向同一個打開的文件句柄73,這可能是調用fork之后出現的。或者某進程通過UNIX域套接字將一個打開的文件描述符傳遞給另一個進程。 此外,進程A的文件描述符0和進程B的文件描述符3分別指向不同的打開文件句柄,但這些打開文件句柄指向同一個i-node表中的相同條目。可能是兩個進程各自對同一個文件調用open打開。同時,在一個進程中兩次打開同一個文件,也會出現這種情況。 這里我們可以得到一些結論:
上面的代碼中有三個文件描述符,都是打開同一個文件,即共享同一個i-node項。不同的是fd2通過調用dup復制文件描述符fd1,因此fd1與fd2共享同一個文件打開句柄。fd3是同一個進程中另一個open操作,因此和fd1對比,兩個文件描述符指向不同的文件打開句柄,但指向同一個i-node項目。下圖展示了它們的關系:
因此,對fd1和fd2的open、write、lseek等操作會使文件偏移量發生改變。fd1寫入“hello”之后,文件偏移量變為6,fd2寫入時在6之后寫入,此時文件中的內容是“helloworld”;
當fd2調用lseek改變文件偏移量為0,之后fd1寫入文件,是在偏移量為0的基礎上寫入,因此覆蓋最初的6字節,文件內容變為“HELLOworld”;對于fd3,因為與fd1和fd2指向不同的文件打開句柄,因此fd1和fd2的操作不影響fd3指向的文件打開句柄的文件偏移量,所以fd3寫入時會覆蓋最初的6字節,此時文件內容變為“yelloworld”。
程序運行結果如下:
結果證實了我們的討論。
總結
以上是生活随笔為你收集整理的文件描述符与打开文件的关系的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 请教怎么用简单的代码解决textarea
- 下一篇: 内存分配