Главная arrow Программирование arrow ARM arrow EFSL: I/O Manager (менеджер ввода/вывода) Friday, August 18 2017  
ГлавнаяКонтактыАдминистрированиеПрограммированиеСсылки
UK-flag-ico.png English Version
GERMAN-flag-ico.png Die deutsche Version
map.gif карта сайта
нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Поделиться:

EFSL: I/O Manager (менеджер ввода/вывода) Версия для печати
Написал microsin   
17.11.2009

Тут представлен дословный перевод раздела 6.4 документации EFSL (версии 2.8, 2005 год), посвященного подсистеме IOMan.

IOManager является вторым по счету самым нижним уровнем библиотеки EFSL (после hwInterface). IOManager отвечает за координацию операций ввода и вывода диска, а также управление системой кеша. Документация описывает вторую реализацию IOMan, которая предоставляет следующие возможности:
    - отложенная запись (delayed write)
    - статистика обращения к буферу
    - экспортируемый для пользователей буфер
    - поддерживает кешированный прямой ввод/вывод (I/O), как и непрямой I/O
    - может выделять память самостоятельно (через стек), или Вы можете это делать вручную (heap).

[Основные операции]

Поскольку ограниченная память присуща большинству встраиваемых устройств, для которых предназначена эта библиотека, в ней предпринято несколько решений с целью минимизировать расход памяти. Некоторые из них потребовали, чтобы разработчики пошли на некоторые уступки. Одна из них - отсутствие защиты памяти, поскольку большинство устройств не имеют памяти для поддержки этой возможности, или вообще не могут делать защиту памяти.
Когда IOMan получает запрос на сектор, он убеждается, что в собственном кеше есть данные сектора, и передает инициатору запроса указатель euint8* на кеш. Таким образом, пользователь свободен от операций с памятью, он просто указывает IOMan, что делать. В этом случае могут быть некоторые ошибки: Вы можете запросить сектор на чтение и потом записать данные в кеш, чем испортить его. Или Вы можете запросить сектор, но никогда не отдаёте его (разновидность утечки памяти), в результате получаете очень плохую производительность и блокирование I/O менеджера (deadlock).

Однако, принимая во внимание малый объем памяти, требуемый для операций, если Вы будете следовать правилам работы с IOMan, то получите отличный кешированный объект, который сделает простой работу написания кода для файловой системы.

[Технология кеша]

Всякий раз, когда ioman получает запрос выбрать сектор (на чтение или запись), он должен будет удостовериться, что имеет, или может получить сектор, который Вы хотите. IOMan следует определенному алгоритму, чтобы проделать это.

1. Сначала он сканирует диапазон кеша, чтобы проверить - есть ли в нем уже этот сектор. Если сектор найден, и был запрос на запись, этот участок кеша помечается как записываемый. Информация по использованию и ссылка инкрементируются, и запрашивающей процедуре передается указатель (на кеш). Если содержимое кеша, соответствующее запрашиваемому сектору, не найдено, то ioman переходит к шагу 2.
2. Когда объект не в кеше, он читается с диска. Объект должен быть выбран с диска и помещён лучше всего в то место памяти кеша, которая еще не содержит ничего полезного. IOMan ищет такое место, которое пока ничем не занято. Если такое место найдено, сектор помещается туда. Иначе IOMan переходит к шагу 3.
3. Поскольку тут ничего не остается, кроме как перезаписать уже заполненный кеш, IOMan сделает попытку найти наименее интересную область кеша. Сначала он ищет кеш, который не помечен на запись, и не имеет пользователей. Затем IOMan выберет тот кеш, на который было меньше всего ссылок. Если такой кеш не найден, IOMan будет искать кеш среди помеченного на запись и не имеющего пользователей, с минимальным количеством ссылок. Поскольку кеш помечен на запись, сначала IOMan сбросит его содержимое на диск (медленная операция). После этого запрашиваемый сектор будет записан в найденное место, и вызывающей функции будет возвращен указатель на него. Если IOMan не сможет найти кеш, который не имеет пользователей, то перейдет к шагу 4.
4. Поскольку все места в кеше заняты, IOMan выберет один для переразмещения. Поскольку этот выбор зависит от многих факторов и весьма сложен, используется система указателей. Алгоритм просматривает каждое место в кеше на предмет количества указаний на него - наименьшее количество указывает на кандидата в переразмещение. 50% указаний производится на кеш, помеченный на запись, поскольку запись сектора самая затратная по ресурсам. Другие 35% - указания на переразмещение этого места в кеше. Это не имеет смысла к перераспределению того же самого буфера. Остальные 15% определяются по количеству ссылок на сектор. После того, как выбран лучший кандидат на переразмещение, IOMan перезапишет это место в кеше содержимым нового сектора. Также в стек поиска кеша будет помещен номер сектора и состояние кеша, чтобы во время освобождения сектора старый сектор мог быть восстанвлен. Если и эта операция не удалась, то происходит переход на шаг 5.
5. Отсюда IOMan возвращает нулевой указатель и устанавливает флаг ошибки.

[Функции]

esint8 ioman_init (IOManager *ioman, hwInterface *iface, euint8* bufferarea)
    Эта функция вызывается для инициализации внутреннего состояния I/O менеджера. Она должна быть первой вызываемой функцией для ioman-объекта. Если этого не сделать, то получится непредсказуемое поведение кода. Функция очищает все внутренние переменные и устанавливает их в состояние по умолчанию, а также настраивает область памяти. Здесь есть две возможности - если Вы передадите нулевой указатель bufferarea, вызываемая функция будет использовать статическую переменную размером в 512 * IOMAN NUMBUFFERS, иначе подразумевается, что Вы самостоятельно выделили память, и будет использоваться предоставленный Вами указатель на эту память.

void ioman_reset (IOManager *ioman)
    Эта функция вызывается из функции ioman_init, она делает сброс всех переменных.

esint8 ioman_pop (IOManager *ioman,euint16 bufplace)
    Эта функция выбирает установки (номер сектора, регистр статуса и использования) из стека и помещает их в обратно в основные регистры. В случае успеха возвращается 0, и в случае ошибки, либо когда в стеке нет элементов для pop, возвращается -1.

esint8 ioman_push (IOManager *ioman,euint16 bufplace)
    Эта функция проталкивает установки кеша в стек кеша, оставляя в целости данные основных регистров кеша. В случае успеха возвращается 0, и в случае ошибки, когда в стеке нет места для push, возвращается -1.

esint8 ioman_readSector (IOManager *ioman, euint32 address, euint8* buf)
    Эта функция производит реальное чтение данных из аппаратуры. Только эта функция вызывается при readBuf(), и здесь может быть реализована политика попыток повторного чтения при ошибке. Эта функция корректно передает поток ошибок на вышележащий уровень. Все вызовы этой функции из iomanager проверяются на возвращаемое значение, и информация об ошибках передается наверх. Параметр address указывает на данные относительно начала диска. Никакие предположения по поводу буфера не делаются, это может быть диапазон памяти кеша, либо область памяти, выделенная пользователем. В случае успеха возвращается 0, и в случае ошибки возвращается -1.

esint8 ioman_writeSector (IOManager *ioman, euint32 address, euint8* buf)
    Эта функция производит реальную запись данных в аппаратуру. Только эта функция вызывается при writeBuf(), и здесь может быть реализована политика попыток повторной записи при ошибке. Эта функция корректно передает поток ошибок на вышележащий уровень. Все вызовы этой функции из iomanager проверяются на возвращаемое значение, и информация об ошибках передается наверх. Параметр address указывает на данные относительно начала диска. Никакие предположения по поводу буфера не делаются, это может быть диапазон памяти кеша, либо область памяти, выделенная пользователем. В случае успеха возвращается 0, и в случае ошибки возвращается -1.

euint8* ioman_getSector (IOManager *ioman,euint32 address, euint8 mode)
    Эта функция наиболее часто вызывают из вышележащих подпрограмм библиотеки. Она предоставляет указатель на память, содержащую адрес номера сектора. Есть несколько режимов, которые Вы можете выбрать или комбинировать (операцией ИЛИ).
    IOM_MODE_READONLY   Этот атрибут говорит ioman, что нужен буфер только для чтения. Это не означает, что Вам разрешают записывать в этот буфер - если Вы так поступите, то получите непредсказуемое поведение. Вы не можете комбинировать эту опцию с IOM_MODE_READWRITE.
    IOM_MODE_READWRITE  Этот атрибут говорит ioman, что нужен буфер не только для чтения, но и для записи. Когда Вы освободите сектор, он будет записан на диск. Это необязательно случится немедленно, хотя Вы можете вызвать функцию ioman_flushRange(). Вы не можете комбинировать эту опцию с IOM_MODE_READONLY.
    IOM_MODE_EXP_REQ    Эта опция говорит ioman, что запрос является исключительным, например - запрос вряд ли случится снова. Библиотека добавляет эти флаги к опциям, когда запрашивается bootrecord, чтобы препятствовать получение запросу высокой оценки, что препятствует удалению этих данных из кеша.

esint8 ioman_releaseSector (IOManager *ioman, euint8* buf)
    Эта функция говорит ioman, что Вы окончили работу с некоторыми элементами кеша. Если забыть вызвать эту функцию, то можно получить deadlock в менеджерах IOMan.

esint8 ioman_directSectorRead (IOManager *ioman,euint32 address, euint8* buf)
    Это вариант обычного получения сектора. Иногда Вам нужен сектор с диска, но все, что Вам нужно сделать с ним - это положить его напрямую в буфер пользователя. Было бы глупо вызвать кэширование сектора, если есть внешнее пространство, доступное для данных сектора. Эта функция получает адрес сектора диска и помещает данные сектора в память, указываемую buf. Если сектор доступен из кеша, он будет просто скопирован функцией memCpy() в буфер пользователя.

esint8 ioman_directSectorWrite (IOManager *ioman, euint32 address, euint8* buf)
    Эта функция базируется на той же философии, что и ioman directSectorRead(), однако вопреки названию, данные проходят через слой кеширования. Если имеется неиспользуемая область кеша (или сектор в области кеша), буфер пользователя копируется в это место и остается там, пока это место не понадобится для других целей, либо пока не будет принудительно сделан flush.

esint8 ioman_flushRange (IOManager *ioman, euint32 address_low, euint32 address_high)
    Эта функция используется для запроса к ioman сбросить в указанном диапазоне все сектора на диск. Например, Вы можете захотеть сделать flush частного диапазона Вашей файловой системы, без ненужного беспокойства для других частей. Диапазон address_low <= n => address_high. Само собой, будут записаны только те сектора, которые помечены на запись.

esint8 ioman_flushAll (IOManager *ioman)
    Эта функция заставит ioman сделать flush out всех частей кеша, помеченных на запись. Если у них не будет никаких пользователей, то они потеряют свою пометку записи.

[Ссылки]

1. Сайт EFSL.
2. IAR EW ARM: работа с файловой системой FAT на карточках SD/MMC.
3. IAR EW ARM: как сделать USB Mass Storage Device на основе MMC/SD.
4. Библиотека EFSL.

Последнее обновление ( 01.12.2009 )
 

Добавить комментарий

:D:lol::-);-)8):-|:-*:oops::sad::cry::o:-?:-x:eek::zzz:P:roll::sigh:

Защитный код
Обновить

< Пред.   След. >

Top of Page
 
microsin © 2017