Проблемы чтения общего буфера в mmap - PullRequest
1 голос
/ 08 февраля 2012

У меня есть модуль ядра, который выделяет большой буфер памяти, этот буфер затем mmap-ed в пользовательское пространство.
Модуль получает некоторые данные с аппаратного обеспечения, а затем помещает новые данные в буфер с флагом перед ним. (память инициализируется в ноль, флаг равен 1).

Программа userpace читает флаг в цикле перед возвратом указателя на действительные данные

упрощенная версия кода:

uint8_t * getData()
{
    while(1)
   {
      if(*((volatile uint32_t*)this->buffer) == 1)
          return this->buffer+sizeof(uint32_t);
   }
}

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

Проблема в том, что после определенного числа правильных чтений эта функция перестает возвращаться.
Может ли это быть связано с кэшированием процессора? Есть ли способ обойти это и убедиться, что чтение производится каждый раз непосредственно из ОЗУ, а не из кэша?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2012

Лучший способ предупредить приложение пользовательского пространства о наличии большего количества данных - это заблокировать его в read() в файловом дескрипторе, предоставленном модулем ядра, при этом модуль ядра разбудит его, когда будет доступно больше данных.

0 голосов
/ 08 февраля 2012

Да, скорее всего, это связано с кэшем процессора на стороне считывателя. Кто-то может подумать, что ключевое слово «volatile» должно защищать от такого рода проблем, но это не совсем правильно, поскольку volatile - это просто указание компилятору не регистрировать переменную, не совсем то же самое, что указывать процессору читать непосредственно из основной памяти. каждый раз.

Проблема должна быть решена на стороне записи. Из вашего описания звучит так, будто запись происходит в модуле ядра и читается со стороны пользователя. Если эти две операции выполняются на разных процессорах (разных доменах кэширования), и нет ничего, что могло бы вызвать недействительность кэша на стороне чтения, вы застрянете на стороне чтения, как вы описываете. Вам нужно принудительно очистить буфер хранилища в ядре linux после выполнения инструкции хранилища. Предполагая, что это ядро ​​Linux, вставка вызова smp_mb сразу после того, как вы установили флаг и значение из модуля, скорее всего, будет работать правильно на всех архитектурах.

...