protobuf無法使用open函式開啟檔案
今天在使用protobuf做簡單的引數存取時發現,Windows下無法使用open函式獲取檔案描述符
open 函式用於開啟和建立檔案。以下是 open 函式的簡單描述
int open(const char *pathname, int oflag, ... );
於是查了下。
在Linux下open函式是在fcntl.h標頭檔案中的(該標頭檔案中包含了許多檔案開啟的模式定義和create、fcntl、open等函式),windows也有該標頭檔案(但僅包含了一些檔案開啟模式的定義)。
因此判定fcntl.h並不是標準庫函式。查了下,果然如此(不得不說基礎知識掌握不牢固啊)。
該標頭檔案不屬於標準庫函式,且Windows下的fcntl.h標頭檔案下沒有該函式並不代表這個功能不能用,或者Windows下不能使用這個功能。畢竟protobuf就提供了這個介面。
查了寫資料,有人說FILE結構體中包含了檔案描述符這個欄位,其形式如下(其中_file就是Linux下的檔案描述符fd):
struct _iobuf { char *_ptr; int _cnt; char *_base; int _flag; int_file;//檔案描述符 int _charbuf; int _bufsiz; char *_tmpfname; }; typedef struct _iobuf FILE;
但是我在VS2015下查找了下,發現其實現形式並非如此,而是這樣:
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // Stream I/O Declarations Required by this Header //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ typedef struct _iobuf { void* _Placeholder; } FILE;
因此認為應該是編譯環境升級導致資料結構與原先發生了一些改變,無法使用(瞎猜的)。
後查閱資料發現vs下可用io.h標頭檔案中的open函式實現獲取檔案描述符的功能。
C標準庫
C標準庫,顧名思義既然是標準,就是由標準組織制定的。
是由“美國國家標準協會(American National Standards Institute,ANSI)”為了規範C語言庫而制定的標準。在最初,各個大學各個公司使用的C語言庫都不盡相同,造成相互移植非常困難,在這個背景下,制定了這個標準。
下面是標準庫函式的標頭檔案:
標準頭名 | 功能 | 描述 |
---|---|---|
<assert.h> | 診斷 |
僅包含assert 巨集。可以在程式中使用該巨集來診斷程式狀態(例如某個變數是否為0等),若檢查失敗,程式終止。 |
<ctype.h> | 字元處理 | 包含判斷字元型別及大小寫轉換的函式。 |
<errno.h> | 錯誤監測 |
提供了errno 。可以在呼叫特定庫函式後檢測errno 的值以判斷呼叫過程中是否有錯誤發生。 |
<float.h> | 浮點數特性 | 提供了描述浮點數特性的巨集。 |
<limits.h> | 整型特性 | 提供了描述整數型別和字元型別特性的巨集。 |
<locale.h> | 本地化 | 提供了一些支援程式國際化的函式。 |
<math.h> | 數學計算 | 提供了大量用以數學計算的函式。 |
<setjmp.h> | 非本地跳轉 |
提供了用於繞過正常的函式返回機制,從一個函式跳轉到另一個正在活動的函式的setjmp 和longjmp 函式。 |
<signal.h> | 訊號處理 | 提供了包括中斷和執行時錯誤在內的異常情況處理函式。 |
<stdarg.h> | 不定引數 | 提供了支援函式處理不變個數的引數的工具。 |
<stddef.h> | 常用定義 | 提供了常用的型別和巨集。 |
<stdio.h> | 輸入輸出 | 提供了大量輸入輸出函式。 |
<stdlib.h> | 常用實用函式 | 提供了大量實用的函式。 |
<string.h> | 字串處理 | 提供了大量字串處理函式。 |
<time.h> | 日期和時間 | 提供了獲取、操縱和處理日期的函式。 |
C執行庫
C執行庫,是和平臺相關的,即和作業系統相關的。
它由不同作業系統不同開發平臺提供不同的C執行庫。但是C執行庫的部分實現是基於C標準庫的,即C執行庫是各個作業系統各個開發工具根據自身平臺開發的庫,某種程度上,可以說C執行庫是C標準庫的一個擴充套件庫,只是加了很多C標準庫所沒有的與平臺相關的或者不相關的庫介面函式。舉例子如:c標準庫的strcpy函式負責字串的拷貝,但是由於缺少對目地字串緩衝區大小的控制,極有可能導致緩衝區溢位(大量的緩衝區溢位攻擊都是由於這種漏洞而產生的);相反,Windows提供了能夠實現同樣功能的安全的字串拷貝函式,減少了緩衝區攻擊的可能,strcpy_s。這些函式是以c執行庫的方式提供的,當然,不同的作業系統,c執行時庫可能不同,但是對c標準庫的支援是完全一致的,也就是說,在不同的作業系統上,使用同一個c標準庫的函式必然產生一致的結果。
一個C執行庫大致包含了如下功能:* 啟動與退出:包括入口函式及入口函式所依賴的其他函式等。
* 標準函式:由C語言標準規定的C語言標準庫所擁有的函式實現。(C標準庫)
* I/O:I/O功能的封裝和實現,參見上一節中I/O初始化部分。
* 堆:堆的封裝和實現,參見上一節中堆初始化部分。
* 語言實現:語言中一些特殊功能的實現。
* 除錯:實現除錯功能的程式碼。
總結一下,C標準庫就是任何平臺都可以使用的基本C語言庫。而CRT除了將C標準庫加入所屬範圍外,還擴充套件了與平臺相關的介面庫,這些介面實現根據不同平臺呼叫不同平臺的作業系統API。
如下圖所示,採用C標準庫編寫的程式可以應用到windows平臺,也可以應用到linux平臺;而用CRT另外與平臺相關的庫函式編寫的應用程式不能跨平臺執行。
參考資料: