В моем драйвере у меня есть определенное количество физически смежных буферов DMA (например, 4 МБ каждый) для приема данных с устройства. Они обрабатываются аппаратными средствами с использованием списка SG. Поскольку полученные данные будут подвергнуты интенсивной обработке, я не хочу отключать кеш, и буду использовать dma_sync_single_for_cpu после того, как каждый буфер будет заполнен DMA.Linux: как смоделировать последовательность физически смежных областей в пространстве пользователя?
Чтобы упростить обработку данных, я хочу, чтобы эти буферы отображались в виде единого огромного непрерывного кругового буфера в пользовательском пространстве. В случае одного буфера я просто использую remap_pfn_range или dma_mmap_coherent. Однако я не могу использовать эти функции несколько раз для сопоставления последовательных буферов.
Конечно, можно реализовать ошибки операцию в vm_operations так, что он находит PFN соответствующей страницы в правом буфере, и вставляет его в ВМА с vm_insert_pfn.
Приобретение будет очень быстрым, поэтому я не могу обрабатывать отображение, когда поступают реальные данные. Но это можно легко решить. Чтобы все сопоставление было готово до начала сбора данных, я могу просто прочитать весь mmapped буфер в своем приложении до начала сбора, так что все страницы уже вставлены при поступлении первых данных.
Tha ошибка основанный трюк должен работать, но, может быть, есть что-то более элегантное? Только одна функция, которая может быть вызвана несколько раз для постепенного построения всего отображения?
Дополнительная сложность заключается в том, что решение должно быть применимо (с минимальными корректировками) к ядрам, начиная с 2.6.32 до новейшего.
PS. Я видел это annoying post. Есть ли опасность, что если приложение попытается написать что-то в mmapped-буфере (просто сделав на месте обработки данных), мое тщательно построенное отображение будет уничтожено COW?
Я никогда не использовал 'vm_insert_pfn'. Обычно я нахожу логический (ядро виртуальный) адрес в правом буфере, передаю его на 'virt_to_page', чтобы получить' struct page * ', затем вызывается' get_page' на странице и задает 'vmf-> страницу' на странице. Это работает, когда буферная память выделяется '__get_free_pages', но, вероятно, недействительна, когда буферная память выделяется функциями' dma_alloc _...'. В этом случае вы можете вызвать 'dma_mmap_attrs' в цикле из самого обработчика _mmap_, настроив' vma-> vm_start', 'vma-> vm_end' и' vma-> vm_pgoff' перед каждым вызовом и восстановить их в конец. –
Пока ваш _mmap_-обработчик разрешает только общие сопоставления 'vma-> vm_flags & VM_SHARED', я не думаю, что вам нужно беспокоиться о COW. –
К сожалению, * dma_mmap_attrs * впервые появился в 3.5. Я не могу использовать его в совместимом с 2.6.32 драйвером. Я вижу два драйвера в 2.6.32, которые используют * vm_insert_pfn * - i915_gem.c и b3dfg.c. В обоих случаях * get_page * не вызывается перед вставкой. – wzab