Довольно уверен, что я уже знаю ответ на этот вопрос, так как есть связанные вопросы на SO уже (here, here и here ,, и this был полезен) ,,, но я хотел быть абсолютно уверенным, прежде чем погрузиться в ядро- космический водитель земли (никогда там не было).Двусторонняя связь с устройством PCIe через/dev/mem в пользовательском пространстве Linux?
У меня есть устройство PCIe, с которым мне нужно общаться (и наоборот) из приложения в пользовательском пространстве linux. Открыв /dev/mem
, затем mmap
'ing, мне удалось написать драйвер для пользовательского пространства, построенный поверх pciutils, что позволило мне mmap
BAR и успешно записать данные на устройство. Теперь нам нужно, чтобы comm отправился в другое направление, от устройства PCIe до пользовательского приложения linux. Для того, чтобы это сработало, мы полагаем, что нам понадобится большой кусок (~ 100 МБ) физически смежной памяти, который никогда не будет выгружен/заменен. После выделения этот адрес должен быть передан на устройство PCIe, чтобы он знал, где записать свои данные (таким образом, я не вижу, как это может быть виртуальная, сменная память). Есть ли способ сделать это без драйвера пространства ядра? Одна идея здесь была размещена, возможно, мы можем открыть /dev/mem
, а затем подать команду ioctl
, чтобы выделить то, что нам нужно? Если это возможно, я пока еще не смогу найти какие-либо примеры в Интернете, и вам придется исследовать его более интенсивно.
Предполагая, что нам нужен драйвер пространства ядра, лучше всего выделить наш большой патрон во время загрузки, а затем использовать ioremap
, чтобы получить виртуальный адрес ядра, а затем mmap
оттуда в пользовательское пространство, правильно? Из того, что я читал на kmalloc
, мы не будем приближаться к 100 МБ, используя этот вызов, а vmalloc
не годится, так как это виртуальная память. Чтобы выделить при загрузке, драйвер должен быть статически связан с ядром, правильно? Это в основном встроенное приложение, поэтому переносимость для меня не вызывает большого беспокойства. Возможно, работает модуль, а не статически связанный драйвер, но я беспокоюсь, что фрагментация памяти может помешать обнаружению физически смежного региона, поэтому я хотел бы выделить его как можно скорее из включения питания. Любая обратная связь?
EDIT1: Мой процессор - архитектура ARM7.
стрелять, возможно, должен был упомянуть, что процессор, который я использую (по крайней мере на данный момент), является архитектурой ARM7. Не уверен, что это делает ваш ответ спорным или нет. Большое спасибо за информацию, хотя, я обязательно исследую этот метод в ближайшие дни. – yano
Думаю, 32-битная рука не имеет 1G-огромных страниц (может быть, меньше, хотя). Другим способом можно было зарезервировать часть вашей памяти (например, bootparameter ядра «memmap = 100M @ 0x10000000» резервирует 100 МБ в физической памяти 1 ГБ) и mmap из/dev/mem в память процессов. Вы должны убедиться, что ядро не было скомпилировано с CONFIG_DEVMEM_STRICT, однако – Ctx
Для драйвера ядра, 'dma_alloc_coherent' может выделить память, подходящую для доступа как к устройству, так и к CPU. Обработчик операций файла драйвера для 'mmap' может вызывать' dma_mmap_coherent', чтобы сопоставить его с адресным пространством пользователя. Трудность состоит в том, что размер памяти, которую вы можете выделить с помощью 'dma_alloc_coherent', обычно довольно ограничен. Вы можете преодолеть это, используя параметр загрузки ядра 'cma', например. 'CMA = 100M'. На практике вам обычно нужно сделать параметр 'cma' больше, чем вам нужно, поскольку другие драйверы могут украсть некоторые из них до вашего драйвера. –