Простая виртуальная файловая система на 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
}

Вы можете попробовать библиотеку PhysicsFS.

На самом деле это реализовано, так что из опыта здесь:

Первое, что нужно сделать, это использовать классы. Здесь нет 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, что означает, что она, вероятно, войдет в стандартную библиотеку.

Другие вопросы по тегам