Простая виртуальная файловая система на C/C++
Я хотел бы реализовать очень простую Виртуальную файловую систему (VFS), которая поддерживает некоторые базовые операции с файловой системой, такие как fwrite, fopen, fput и т. Д. VFS - это уровень абстракции поверх некоторых конкретных ОС, например, Windows, Linux и т. Д. Предположим сейчас что интерфейс fopen выглядит примерно так
FILE VFS_File_Open( const unsigned char* strFile, int flags );
Теперь мне интересно, как я могу сделать в реальной реализации этого интерфейса различие о том, с какой файловой системой я разговариваю. Есть ли в C что-то, что говорит мне, на какой ОС работает приложение, чтобы я мог сделать что-то вроде этого:
FILE VFS_File_Open( const unsigned char strFile, int flags )
{
int OS = getOSID();
if (0S == 1)
//implement here the system calls required to open a file on a WIN OS
else if (OS == 2)
//implement here the system calls required to open a file on a Linux OS
etc
}
РЕДАКТИРОВАТЬ:
Теперь мне интересно, если кто-нибудь знает, где я могу найти системные вызовы для файловых операций для Windows? Их легко найти для Linux, но я изо всех сил пытался найти что-то подобное для Windows, например, мне было бы интересно, чтобы системные вызовы открывали файл, записывали файл и т. Д.
На другом примечании: C stdio.h предлагает ряд операций ввода-вывода в стойке, таких как
FILE * fopen (const char *filename, const char *opentype)
Другими словами, мне не нужно переопределять подпрограмму fopen в моей VFS, поскольку библиотека Gnu C заботится о том, с какой ОС она имеет дело, не так ли? Мне просто нужно реализовать функциональность, которая не поддерживается библиотекой stdio, например, создание каталогов, которые отличаются от файловой системы к файловой системе?
Спасибо
6 ответов
Возможно, самой простой / чистой реализацией было бы создание двух отдельных библиотек, одной для Windows и одной для Linux, без засорения вашего кода каскадным if
а также switch
заявления. Библиотеки будут реализовывать те же функции, которые определены в общем заголовке.
Также помните, что код внутри вашего чека OS == something
будет компилироваться и связываться во всех системах, поэтому, например, библиотека, скомпилированная в linux, должна иметь возможность разрешать системные вызовы Windows...
Я думаю, что разделение вещей (разные ОС, разные файлы cpp) - самое простое решение.
РЕДАКТИРОВАТЬ:
Если вы используете C++, почему бы просто не полагаться на потоки? Стандартная библиотека уже обеспечивает функциональность, которую вы пытаетесь реализовать, и доступна на всех платформах.
В противном случае, вот ссылка на функции управления файлами Windows.
ВТОРОЙ РЕДАКТИРОВАТЬ:
Если вам нужна библиотека кроссплатформенной файловой системы, поддерживающая, помимо прочего, создание каталогов, вы можете проверить библиотеку файловой системы boost.
Я не думаю, что вы можете скомпилировать модуль для разных ОС, так, как вы хотите.
// Make the distinction at compile time,
FILE VFS_File_Open( const unsigned char strFile, int flags )
{
#ifdef _WINDOWS
//implement here the system calls required to open a file on a WIN OS
#endif
#ifdef _LINUX
//implement here the system calls required to open a file on a Linux OS
#endif
etc
}
На самом деле это реализовано, так что из опыта здесь:
Первое, что нужно сделать, это использовать классы. Здесь нет fopen()
эквивалент. Если есть флаги, они будут перечислением. Имена файлов сейчас wchar_t.
Второе, что нужно сделать, это выделить зависящие от ОС части вашего класса файлов. Они должны быть в отдельных методах. Вы перемещаете их в отдельный файл. Для каждой имеющейся у вас ОС будет свой файл, реализующий одни и те же методы. Когда вы связываете свое приложение, вы знаете целевую архитектуру и можете выбрать правильные версии.
Стандарт С не имеет такой функции. Обратите внимание, что понятие "конкретная ОС" также немного расплывчато: Windows XP и Windows Vista - это одна и та же "конкретная ОС" или разные? CentOS и Ubuntu - это одна и та же ОС или разные?
Очевидно, вы ищете только различия API, поэтому в большинстве случаев вы, вероятно, можете игнорировать различия версий и различий в распределении (хотя и в Windows, и в Linux время от времени появляются новые системные вызовы). В этом случае лучше всего выполнить препроцессор условной компиляции - поскольку код, выполняющий специфичные для Linux вызовы, даже не будет компилироваться в Windows.
Традиционно системные компиляторы имеют различные предопределенные макросы. Вот несколько таких макросов в соответствующих системах: _WIN32
, __linux
, __linux__
, __AIX__
, __hpux
... Если вам нужно идентифицировать конкретную систему, вам следует снова обратиться к SO.
Если вы ищете способ абстрагироваться от свойств файловой системы, которую вы используете (разделители путей и т. Д.), И если вы довольны решением только для C++, взгляните на Boost.Filesystem.
Пути могут быть указаны в формате переносимого универсального пути (в основном формат POSIX) и автоматически конвертируются в собственный формат:
path my_path( "some_dir/file.txt" );
Элементы могут быть объединены на пути, используя /
оператор, и результат может быть затем непосредственно использован для открытия файла:
ifstream file1( my_path / "foo/bar" );
Более того, эта функция является частью Технического отчета 2, что означает, что она, вероятно, войдет в стандартную библиотеку.