2012-02-07 2 views
1

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

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

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

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

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

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

+0

Это очень характерно для архитектуры, и вы не сказали нам свою архитектуру. В целом, излучение барьера хранения/выпуска после записи в ядре и барьер загрузки/получения перед чтением в пользовательском пространстве должно быть достаточным, если это действительно проблема. – Useless

+0

@ Lifesworder выглядит так, будто вы новый пользователь, но этикет здесь требует ответа, когда вы задавали вопрос, и им предлагаются некоторые ответы. – chetan

+0

Приносим извинения, сроки, многое сделать :). Я не уверен, что вызвало проблему в первую очередь, но кажется, что удаление флагов MAP_SHARED и MAP_LOCKED из обработчика mmap ядра-пространства устраняло проблему ... – Lifesworder

ответ

0

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

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

+0

Поскольку я тестировал на одноядерном процессоре, это не помогло моей проблеме, но ваш ответ пригодится, когда мне придется переносить это, чтобы работать на многоядерном процессоре (который я буду). – Lifesworder

+1

ahh ... интересный. Как-то в наши дни легко предположить, что все работают над многоядерными системами. – chetan

0

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

Смежные вопросы