системные вызовы не работают для iomapped памяти в linux.

Я сопоставляю некоторую память ввода-вывода с областью vmalloced в драйвере. Я также делюсь этой областью с пользовательскими процессами, используя флаг (PAGE_SHARED в ioremap_page_range).

Теперь я могу получить доступ к этой общей памяти в пространстве пользователя. Я могу писать и читать в эту память. Однако, если я передам эту память в качестве буфера для системных вызовов, таких как recv или send, вызовы завершатся ошибкой с плохой памятью (Memory not mapped into user process).

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

код драйвера:

shared_buf = __get_vm_area(size, VM_IOREMAP, VMALLOCS_START, VMALLOC_END); 
ioremap_page_range(shared_buf->addr, size, phy_addr_of_io, PAGE_SHARED);      

После этого я делаю вызов ioctl и передаю этот адрес shared_buf->addr в приложение пользовательского пространства.
Я пишу и читаю, используя этот адрес. Тогда я делаю

ret = recv(sockfd, shared_buf->area, 0) and I get an error "bad addr".   

Вместо этого, если я попытаюсь

ret = recv(sockfd, local_buf, size, 0);  
memcpy(shared_buf->addr, local_buf, size); Then it goes without issues.   

(Отказ от ответственности: я использую shared_buf->area в потоках, которые не выполняли IOCTL. Однако это тот же процесс.)

Может кто увидит ошибку?


person agent.smith    schedule 29.03.2012    source источник
comment
Возможно, вы захотите обновить это снова, чтобы дать вашему recv вызову достаточно аргументов.   -  person Nemo    schedule 30.03.2012


Ответы (1)


Все системные вызовы проверяют, что переданный указатель находится в пользовательской части адресного пространства. пространство vmalloc не находится в этой пользовательской части; следовательно, вы не можете использовать его для системных вызовов. Что еще более важно, не давайте процессам пользователя прямой доступ к памяти в адресном пространстве vmalloc. Это просто напрашивается на неприятности. И, вероятно, ужасно небезопасно — могут ли другие процессы получить к нему доступ? Вместо этого напишите файл с поддержкой mmap.

person bdonlan    schedule 30.03.2012
comment
@bdolan: у меня была заминка, что должна быть проверка, находится ли адрес в пользовательском пространстве. Однако мне также было интересно, почему проверка не выполняется для бита супервизора в таблице страниц. Возможно, разработчики ядра не ожидают, что программисты будут использовать буфер ядра. (Я знаю, что mmap — это обычный способ сделать это.) Я использовал этот ужасный метод обмена мемами, так как хотел что-то быстро проверить и наткнулся на эту проблему. Спасибо. - person agent.smith; 30.03.2012
comment
@agent.smith, на самом деле поиск страницы в таблице страниц медленный. Ядро просто проверяет, находится ли он в диапазоне пользовательского пространства, а затем напрямую обращается к нему (даже в кольце 0 ЦП будет учитывать биты отсутствия или защиты от записи). Единственным исключением являются некоторые очень ранние модели процессоров 386, в которых ядро ​​действительно проверяет таблицу страниц, но опять же, это довольно медленно. - person bdonlan; 31.03.2012