Linux中文件描述符fd與文件指針FILE*互相轉(zhuǎn)換實例解析
本文研究的主要是Linux中文件描述符fd與文件指針FILE*互相轉(zhuǎn)換的相關內(nèi)容,具體介紹如下。
1.文件描述符fd的定義:文件描述符在形式上是一個非負整數(shù)。實際上,它是一個索引值,指向內(nèi)核為每一個進程所維護的該進程打開文件的記錄表。當程序打開一個現(xiàn)有文件或者創(chuàng)建一個新文件時,內(nèi)核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫往往會圍繞著文件描述符展開。但是文件描述符這一概念往往只適用于UNIX、Linux這樣的操作系統(tǒng)。
2.文件指針FILE定義說明文件指針的一般形式為:
FILE *指針變量標識符;
其中FILE應為大寫,它實際上是由系統(tǒng)定義的一個結(jié)構(gòu),該結(jié)構(gòu)中含有文件名、文件狀態(tài)和文件當前位置等信息。在編寫源程序時不必關心FILE結(jié)構(gòu)的細節(jié)。
使用系統(tǒng)調(diào)用的時候用文件描述符的時候比較多,但是操作比較原始。C庫函數(shù)在I/O上提供了一些方便的包裝(比如格式化I/O、重定向),但是對細節(jié)的控制不夠。
如果過度依賴其中的一種只會徒增麻煩,所以知道兩者的轉(zhuǎn)換是很有必要的。FILE*是對fd的封裝
當然,有人會說知道文件路徑的話重新打開就是了,但是這會產(chǎn)生競爭條件(Race Conditions),首先重新打開文件,相當于是2個fd指向同一文件,然后如果在打開的期間文件被刪除了又被新建了一個同名文件,2個fd指向的便是不同的文件。
glibc庫提供了兩個轉(zhuǎn)換函數(shù)fdopen(3)和fileno(3),都是<stdio.h>中的
FILE *fdopen(int fd, const char *mode);
int fileno(FILE *stream);
PS:為了節(jié)省篇幅,還是繼續(xù)忽略返回值的檢查。
來看看測試吧,是不是我們想的那樣。
#include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { const char* filename = "new.txt"; int fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); FILE* fp = fdopen(fd, "w+"); int fd2 = fileno(fp); printf("fd=%d | fd2=%d\n", fd, fd2); fclose(fp); close(fd); return 0; }
$ gcc test.c $ ./a.out fd=3 | fd2=3
參考fileno手冊:
The function fileno() examines the argument stream and returns its integer descriptor.
FILE是對fd的封裝,fileno()是直接取得被封裝的fd,因此并未創(chuàng)建新的fd指向該文件。
參考fdopen手冊:
The fdopen() function associates a stream with the existing file descriptor, fd. The mode of
the stream (one of the values "r", "r+", "w", "w+", "a", "a+") must be compatible with the
mode of the file descriptor.
fdopen()是講流(FILE對象)與已存在的文件描述符fd進行關聯(lián),因此也是未創(chuàng)建新的fd。值得注意的是,F(xiàn)ILE指針的模式(mode)必須與文件描述符的模式兼容。
關于mode參數(shù)先擱置會兒,目前我們知道的是,使用fileno和fdopen進行轉(zhuǎn)換,都是在原有的fd上進行操作,并未產(chǎn)生新的fd。那么,再次審視剛才的代碼,是否發(fā)現(xiàn)了問題?
我們來檢查下close(fd)的返回值,把close(fd)改成下列代碼
if (-1 == close(fd)) { perror("close"); exit(1); }
$ gcc test.c $ ./a.out close: Bad file descriptor
沒錯,fclose在關閉文件指針的時候,內(nèi)部其實也關閉了文件描述符(否則資源就泄露了),既然這里fp內(nèi)部的文件描述符和fd是同一個,當fp被關閉時,fd也被關閉了,再次關閉fd就會出現(xiàn)“損壞的文件描述符”錯誤。
OK,現(xiàn)在回顧下fopen的第2個參數(shù),又r/r+/w/w+/a/a+一共6種設置(windows平臺的rb/rb+/wb/wb+暫且不談),對比Linux手冊我將對應的open設置列出來
依然是進行測試,修改fd_mode和fp_mode,看看實驗結(jié)果
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> const int security = S_IRUSR | S_IWUSR; const int fd_mode = O_RDWR | O_CREAT | O_TRUNC; const char* fp_mode = "r"; int main() { int fd = open("new.txt", fd_mode, security); FILE* fp = fdopen(fd, fp_mode); if (fp == NULL) { perror("fdopen"); exit(1); } close(fd); return 0; }
在fd_mode等價于"w+"時,fp_mode的6種設置(r/r+/w/w+/a/a+)均返回非空指針。
在fd_mode等價于"w"時,fp_mode6種設置只有"a"和"w"返回非空指針。
繼續(xù)嘗試"r"/"r+"/"a"/"a+"的設置,可以發(fā)現(xiàn)所謂“兼容”只與讀寫權限有關,O_RDWR兼容O_RDONLY和O_WRONLY,而后兩者則只與自身兼容。
有意思的是O_APPEND(在末尾添加)和O_TRUNC(截斷文件從頭添加)也兼容。
The file position indicator of the new stream is set to that
belonging to fd, and the error and end-of-file indicators are cleared. Modes "w" or "w+" do
not cause truncation of the file. The file descriptor is not dup'ed, and will be closed when
the stream created by fdopen() is closed.
繼續(xù)查看fdopen的手冊內(nèi)容,可以看到"w"和"w+"在這里不會導致文件截斷。
后一句也印證了我們前面的實驗結(jié)果:文件描述符不會被復制,文件指針被關閉時文件描述符也會被關閉。
PS:其實fdopen的手冊上還有最后一句:The result of applying fdopen() to a shared memory object is undefined.
將fdopen用于共享內(nèi)存對象的結(jié)果是未定義的。
總結(jié)
以上就是本文關于Linux中文件描述符fd與文件指針FILE*互相轉(zhuǎn)換實例解析的全部內(nèi)容,希望對大家有所幫助。感興趣的朋友可以繼續(xù)參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
相關文章
Jexus 5.8.2正式發(fā)布! 為Asp.Net Core生產(chǎn)環(huán)境提供平臺支持
Jexus 5.8.2正式發(fā)布!Jexus支持ASP.NET、PHP為特色的集高安全性和高性能為一體的WEB服務器和反向代理服務器,感興趣的小伙伴們可以參考一下2017-06-06Apache Shiro 使用手冊(四) Realm 實現(xiàn)
在認證、授權內(nèi)部實現(xiàn)機制中都有提到,最終處理都將交給Real進行處理。因為在Shiro中,最終是通過Realm來獲取應用程序中的用戶、角色及權限信息的2014-06-06Linux初始化系統(tǒng)盤后重新掛載數(shù)據(jù)盤方法
在本篇文章中我們給大家分享了Linux初始化系統(tǒng)盤后重新掛載數(shù)據(jù)盤的解決方法,有需要的朋友們可以參考下。2018-09-09linux操作系統(tǒng)原理 linux系統(tǒng)基礎教程
很多對linux操作系統(tǒng)有興趣的朋友想有一個深入的學習,本篇文章給大家詳細講解了linux操作系統(tǒng)的原理,希望能夠?qū)δ阌兴鶐椭?/div> 2018-01-01Linux服務器如何查看每個用戶或者當前用戶的磁盤占用量及文件同步
這篇文章主要介紹了Linux服務器如何查看每個用戶或者當前用戶的磁盤占用量及文件同步問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-02-02最新評論