Ответ 1
От тех трех факторов, которые вы указали только в первом, действительно правильно. Что касается остального - не совсем. Кодер пространства пользователя может выполнять операции DMA - никаких проблем с этим. Существует много компаний-производителей оборудования, которые используют эту технику в своих продуктах. Также возможно иметь приложение, управляемое прерываниями, даже когда все операции ввода-вывода выполняются с полным обходом ядра. Конечно, не так просто сделать mmap()
на /dev/mem
.
У вас должна быть минимальная часть вашего драйвера в ядре - это необходимо для обеспечения вашего пользовательского пространства с минимальным минимумом, который требуется от ядра (потому что, если вы думаете об этом - /dev/mem
, также резервное копирование драйвером персонального устройства).
Для DMA это на самом деле слишком прост - все, что вам нужно сделать, это обработать запрос mmap
и сопоставить буфер DMA в пространстве пользователя. Для прерываний - это немного сложнее, прерывание должно обрабатываться ядром, независимо от того, что ядро может не выполнять никакой работы и просто просыпать процесс, который вызывает, скажем, epoll_wait()
. Другой подход заключается в том, чтобы доставить сигнал к процессу, как это сделано DOSEMU, но это очень медленно и не рекомендуется.
Что касается вашего фактического вопроса, одним из факторов, который вы должны принять во внимание, является совместное использование ресурсов. Пока вам не нужно делиться устройством с несколькими приложениями, и нет ничего, что вы не можете сделать в пользовательском пространстве - идите в пространство пользователя. Вероятно, вы сэкономите массу времени в течение цикла разработки, поскольку код пользовательского пространства очень прост. Когда, однако, двум или более приложениям необходимо разделить устройство (или его ресурсы), то есть вероятность, что вы потратите огромное количество времени, чтобы это стало возможным - просто представьте себе одновременное одновременное воспроизведение нескольких процессов, связанных с краской, сбоем, сопоставлением (той же?) Памяти и т.д. И в конце концов, IPC обычно выполняется через ядро, поэтому, если приложение должно начать "разговаривать" друг с другом, производительность может сильно ухудшиться. Тем не менее, это все еще выполняется в реальных приложениях для определенных приложений с критическими характеристиками, но я не хочу вдаваться в эти детали.
Другим фактором является инфраструктура ядра. Скажем, вы хотите написать драйвер сетевого устройства. Это не проблема для этого в пользовательском пространстве. Однако, если вы это сделаете, вам также понадобится написать полный сетевой стек, так как не будет возможно использовать Linux по умолчанию, который живет в ядре.
Я бы сказал, что вы хотите использовать пространство пользователя, если это возможно, и объем усилий, направленных на то, чтобы сделать работу, меньше, чем запись драйвера ядра, и помня, что в один прекрасный день может потребоваться переместить код в ядро. На самом деле, это обычная практика, заключающаяся в том, что один и тот же код компилируется как для пространства пользователя, так и для пространства ядра в зависимости от того, определен ли какой-либо макрос или нет, поскольку тестирование в пользовательском пространстве намного приятнее.