2015-06-11 28 views
4

它經常會注意到,如果已經有方法創建「虛擬FILE」併爲緩衝區滿了,輸入請求,關閉,沖洗等事件附加必要的回調,我將能夠優雅地解決C中的實際問題。然後應該可以使用大部分的功能,例如, fprintf不變。 有沒有一個框架可以做到這一點?如果不是,至少在某些平臺上,適度的努力是否可行?虛擬化C的FILE *接口有多大的可行性?

可能的應用是:

  • 寫入或從存儲器的動態或靜態區域讀取。
  • 並行寫入多個文件。
  • 從線程或協同例程中讀取數據。
  • 將過濾器應用於其他(虛擬或實際)FILE
  • 支持間接文件格式(如#include)。
  • C預處理器(?)。

我不是在一個框架不太感興趣的特定情況下的解決方案,讓你滾你自己FILE。我也不是在尋找一個虛擬文件系統,而是我可以傳遞給CRT的虛擬FILE*

令我失望的是,我從未見過這樣的事情;就我所見,C11認爲FILE完全取決於語言實現者,如果希望將語言(+庫)規範保持爲小而悲傷,如果將其與Java I/O流進行比較,這可能是合理的。我覺得虛擬FILE必須可以用C運行時的任何(完全)開源實現,但我想可能有大量的細節使它比看起來更復雜,如果它已經完成了,重複這些努力將是一件恥辱。最好不要修改CRT代碼。如果沒有開源代碼,人們可能會對所提供的功能進行逆向工程,但是我擔心,除非承諾使用一組接口,否則結果將太脆弱,無法修改不支持的功能。我想,任何一個可以編寫設備驅動程序的系統都可以創建一個虛擬設備,但我懷疑是不必要的低層次,需要編寫特權代碼。

我不得不承認,雖然我的代碼可以從虛擬FILE中受益,但我目前沒有這方面的要求;儘管如此,這是我經常想到的事情,而且我想其他人可能會感興趣。

這有些類似於a-reader-interface-that-consumes-files-and-char-in-c,但是那裏的提問者不希望返回虛擬的FILE;但是,答案是fmemopen,確實如此。

+0

你看過[libfuse](http://fuse.sourceforge.net/)嗎?它允許你通過回調實現你自定義的文件系統(ioctl,read,stat,write,...) – mpromonet

+0

@mpromonet:不,我不熟悉libfuse,但是你的描述聽起來很有希望......但是當我看起來我看到它聽起來有點不同:我想要一個虛擬的(C)'FILE',我可以傳遞給例如'fprintf',而不是虛擬文件(在存儲介質上)。但我認爲libfuse可能會使用相關技術。 – PJTraill

+0

C是*旨在*被設計爲沒有I/O。所有的I/O都藏在圖書館裏。這使得C便攜。 C中有什麼文件?可能是一個字節數組;但也許是可以尋求的。語義可能會蔓延,但僅限於語義層面。 – wildplasser

回答

5

沒有用於創建虛擬FILE *的標準C接口,但GNU和BSD標準庫都包含一個。在linux(glibc)上,你可以使用fopencookie;在大多數* BSD系統上,funopen(包括Mac OS X)。(見注1)

這兩個接口是相似的,但在一些細節上略有不同。但是,將爲一個接口編寫的代碼適用於另一個接口通常非常簡單。

這些不是完整的虛擬化。他們將FILE*與四個回調和void*上下文關聯(fopencookie中的「cookie」)。回調是read,write,seekclose;對於flushtell操作沒有回調。儘管如此,這對於許多簡單的FILE*適配器來說已經足夠了。

舉個簡單的例子,看Write simultaneousely to two streams的兩個答案。


注:

  1. funopen從 「功能開放」 衍生,而不是從 「文件未打開」。
+0

有趣。謝謝! –

+0

非常感謝,'fopencookie'聽起來像我的意思; 'funopen'鏈接超時(可能是我的VPN)。我會仔細觀察一下並給它一些時間,但我懷疑我會接受這個答案。這聽起來像是屬於標準C11 +庫的東西! – PJTraill

+1

@PJTraill:如果您的VPN更喜歡,可以爲man funopen添加一個apple.com鏈接。國際海事組織,如果它被添加到C或甚至是Posix,接口將需要更完整。 – rici