Mumufs: виртуальная файловая система для поддержки IPC типа много-ко-много

Author / Автор: Сергей Сацкий
Publication date / Опубликовано: 15.07.2007
Version / Версия текста: 1.0

Основные характеристики и пример сценария

Основные характеристики mumufs перечислены ниже:

  • Mumufs является файловой системой полностью располагающейся в оперативной памяти.
  • Mumufs поддерживает обычные файлы, подкаталоги, символические и жесткие ссылки.
  • С каждым обычным файлом mumufs ассоциирует блок данных произвольного размера. Операции записи и чтения для файла соответствуют операциям записи и чтения для соответствующего блока данных.
  • Каждая последующая успешная операция записи замещает предыдущий сохраненный блок данных.
  • Каждая новая операция записи и чтения должна производиться со смещением 0 относительно начала файла. Операция считается успешно завершенной, только если блок данных был прочитан или записан полностью.
  • Для каждого файла допускается одновременное множественное открытие файла и на запись и на чтение.
  • Поддерживаются блокируемый и неблокируемый ввод вывод.
  • Поддерживаются операции select и poll.

Рассмотрим подробнее один из возможных сценариев. Предположим, что имеется два процесса, номер 1 и номер 2, читающих из файла /mnt/mumu/file1 и два процесса, номер 3 и номер 4, производящих запись в файл.

Файловая система mumufs монтируется на точку /mnt/mumu. Процесс номер 3 открывает файл /mnt/mumu/file1на запись. Файл еще не существует, поэтому mumufs создает необходимые структуры данных в памяти. Процесс номер 3 записывает в файл блок данных размером 2048 байт. Mumufs размещает в памяти блок подходящего размера и копирует данные от процесса в выделенный блок. Процесс номер 1 открывает файл /mnt/mumu/file1 на чтение и получает 2048 байт. Если буфер чтения процесса номер 1 меньше 2048 байт, процесс получит уведомление об ошибке чтения. Если буфер достаточен, то данные будут скопированы процессу, а mumufs сделает отметку, что процесс уже прочитал текущий доступный блок данных. Далее процесс номер 1 повторяет операцию чтения. Mumufs учитывает, что процесс номер 1 уже прочитал доступный блок данных и блокирует операцию чтения. Далее процесс номер 4 открывает файл /mnt/mumu/file1на запись и производит запись 256 байт. Mumufs замещает первый блок данных новым блоком и разблокирует все заблокированные на чтении процессы, в данном случае процесс номер 1. Процесс номер 1 читает 256 байт второго блока и при последующем чтении снова будет заблокирован. Далее процесс номер 2 открывает файл /mnt/mumu/file1 на чтение и выполняет операцию чтения. Mumufs копирует 256 байт доступного блока в процесс номер 2. При следующем чтении процесс номер 2 будет заблокирован. Далее процесс номер 1 выполняет запись 512 байт. Новый блок замещает старый, а процессы номер 1 и 2 разблокируются для возможности чтения нового доступного блока.

Удаление файла ведет к освобождению блока памяти, ассоциированного с файлом. Закрытие файла всеми заитересованными процессами не приводит к освобождению памяти, занятой последним записанным блоком. Размонтирование файловой системы ведет к освобождению всех размещенных блоков данных.

Таким образом, единицой транзакции для mumufs является блок данных. Имя файла в mumufs используется в качестве уникального идентификатора блока произвольных данных. Время жизни блока совпадает с временем жизни файла в mumufs, то есть либо до момента удаления файла, либо до момента размонтирования файловой системы.

Mumufs может быть смонтирована произвольное количество раз.

Примером применения mumufs могут служить системы с графическим интерфейсом пользователя. Например, состоянием батарейки в мобильном телефоне могут интересоваться сразу несколько процессов. Это могут быть процессы, отображающие иконку в строке состояния, показывающие подробное состояние батарейки в отдельном окошке и процессы, запускающие систему энергосбережения или оповещения и т.п. Всем этим процессам необходимо только текущее состояние, история изменения состояния не требуется. При использовании mumufs процессу поставщику данных нет необходимости знать, сколько потребителей имеется, и сколько их будет в будущем. Поставщик открывает файл и обновляет значение по мере необходимости. Для потребителей реализация обмена также очень проста, необходимо открыть файл и читать подходящим образом данные. Единственное требование это договоренность о формате данных и имени в файловой системе.

Блокировки

Mumufs поддерживает блокируемый и неблокируемый ввод-вывод. Признак блокируемого или неблокируемого ввода-вывода оказывает влияние только на операции чтения.

В случае блокируемого чтения процесс блокируется, если нет блока данных, который процесс успешно прочитал. Разблокировка процесса производится либо когда новый блок данных становится доступен, либо когда процесс принимает сигнал.

Особенности реализации

Mumufs использует блокировки чтения-записи для обеспечения безопасности доступа к данным. Это определяет приоритет операций записи перед операциями чтения.

Mumufs поддерживает расширенные атрибуты файлов. Это позволяет поставщикам данных документировать назначение блоков произвольным образом, например в виде произвольного текста.

Поскольку mumufs поддерживает интерфейс файловой системы, то возможно использование всех стандартных файловых утилит UNIX. Стоит, однако, помнить об особенностях реализации mumufs. Например, если пользователь выдал команду cat /mnt/mumu/batteryStatus, то на экране будет напечатано содержимое блока данных, однако после этого cat будет заблокирован, так как cat открывает файлы в блокируемом режиме. Как только поставщик данных обновит содержимое /mnt/mumu/batteryStatus, так cat выведет новое значение и будет снова заблокирован. Однако, всегда можно прервать cat с помощью комбинации клавиш Ctrl+C. Эти ограничения затрудняют использование утилит в пакетном режиме, однако, легкость в использовании и наблюдаемость mumufs остается гораздо лучше, чем в случае традиционных механизмов межпроцессного взаимодействия.

Безопасность

Досту к файлам mumufs предоставляет на основе традиционной схемы UNIX для дисковых файловых систем.

Особенности использования

Поскольку mumufs использует блок данных как единую транзакцию, то операции записи и чтения всегда должны начинаться со смещения 0, а операции seek вообще не поддерживается (так же как и файловые блокировки). Это обстоятельство ведет к особенностям использования mumufs, которые описаны ниже.

Стандартная библиотека libc предлагает разработчику функции работы с файлами, начинающиеся с префикса f: fopen(:), fclose(:), fread(:), fwrite(:) и т.д. С помощью этих функций можно работать с файлами и, в том числе, казалось бы, с файлами, располагающимися на mumufs. Однако libc версия fwrite(:) выполняет склейку маленьких пакетов данных для оптимизации операции записи (с настройкой системы буферизации по умолчанию). Например, если дважды выполнена операция записи блоков данных по 2 байта каждый, то до файловой системы дойдет только один вызов записи с блоком данных длиной 4 байта. Это делает неудобным использование функций этой группы с mumufs.

Существует возможность воспользоваться и другой группой функций для работы с файлами: open(:), close(:), read(:), write(:) и т.д. Эти функции не выполняют никаких дополнительных действий с блоками данных и хорошо подходят для использования с mumufs файлами.

Для облегчения работы с файлами mumufs разработана C++ библиотека шаблонов libmumu++. Состав библиотеки описан в разделе ниже.

Libmumu++

Библиотека шаблонов libmumu++ предлагает всего один шаблонный класс Entry. Класс предлагает C++ обертку для работы с файлами, расположенными на mumufs. Передаваемый шаблону тип используется как блок обмена данными. При этом предполагается, что данные типа занимают непрерывную область в памяти.

Пример программы для записи целых чисел с использованием libmumu++.

#include "mumulib.h"
using namespace mumu;

int  main( int  argc, char **  argv )
{
    try
    {
        Entry< int >      Value( "/mnt/mumu/one" );
        Entry.Write( 154 );
    }
    catch ( std::exception &  E )
    {
        return 1;    // Writing error
    }

    return 0;
}

Шаблон Entry по умолчанию открывает указанный файл в режиме блокируемого ввода-вывода. Вторым параметром конструктора можно указать, что файл надо открывать в неблокируемом режиме.

Шаблон Entry поддерживает две версии функций чтения, ориентированных на блокируемый и неблокируемый ввод-вывод. Поддерживается операция select с возможностью указать таймаут ожидания.

Пример программы, использующей функции чтения и select через libmumu++.

#include "mumulib.h"
using namespace mumu;

int  main( int  argc, char **  argv )
{
    try
    {
        int               Value;
        Entry< int >      Blocking( "/mnt/mumu/one" );
        Entry< int >      NonBlocking("/mnt/mumu/one", false );

          // Blocking IO
          // If the file does not exist then we are blocked here
          // Use the first program to put some value in the file
        Value = Blocking.Read();

          // Non-blocking IO
        if ( NonBlocking.Read( &Value ) == 0 )
        {
          // No data available
        }
        else
        {
          // A value is read
        }

          // Select example
          // Use the first program to put update the file content

        struct timeval    Timeout;
        Timeout.tv_sec  = 15;
        Timeout.tv_usec = 0;
        if ( Blocking.Select( &Timeout ) )
        {
          // New data arrived
          Value = Blocking.Read();
        }
        else
        {
          // No new data and the timeout exceeded
        }

          // 0 - waits forever. Use the first program
        if ( Blocking.Select( 0 ) )
        {
          // New data arrived
          Value = Blocking.Read();
        }
        else
        {
          // No new data and the timeout exceeded
        }
    }
    catch ( std::exception &  E )
    {
        return 1;    // Writing error
    }

    return 0;
}

Класс Entry поддерживает специализацию всех функций членов для std::string.

Более подробную документацию по библиотеке можно сгенерировать с помощью doxygen - библиотека содержит все необходимые комментарии.


Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.

Разрешается копирование и распространение этой статьи любым способом без внесения изменений, при условии, что это разрешение сохраняется.
Last Updated: December 15, 2007