linux中iomapped内存的系统调用失败。

linux中iomapped内存的系统调用失败。,linux,linux-kernel,device-driver,Linux,Linux Kernel,Device Driver,我正在将一些io内存映射到驱动程序中的vmalloced区域。我还使用flag(PAGE\u SHARED在ioremap\u PAGE\u范围内)与用户进程共享此区域 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); 现在我可以访

我正在将一些io内存映射到驱动程序中的vmalloced区域。我还使用flag(
PAGE\u SHARED
在ioremap\u PAGE\u范围内)与用户进程共享此区域

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);      
现在我可以访问用户空间中的共享内存。我可以写和读这些记忆。但是,如果我将此内存作为缓冲区传递给系统调用,如
recv
send
,则调用失败,内存不好(
内存未映射到用户进程中

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);      
但是,我确信我的缓冲区没有任何问题。因此,在我为系统调用共享内存和错误检查的方式中似乎存在一些冲突

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);      
驱动程序代码:

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调用,并将这个共享的\u buf->addr传递给用户空间应用程序。
我用这个地址写和读。那我会的

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);      
ret = recv(sockfd, shared_buf->area, 0) and I get an error "bad addr".   
如果我试着去做的话

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);      
ret = recv(sockfd, local_buf, size, 0);  
memcpy(shared_buf->addr, local_buf, size); Then it goes without issues.   
(免责声明:我确实在没有执行IOCTL的线程中使用了
shared\u buf->area
。但是这是相同的过程。)

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);      

有人看到错误吗?

系统调用all验证传入的指针是否在地址空间的用户部分。vmalloc空间不在此用户部分中;因此,不能将其用于系统调用。更重要的是,不要让用户进程直接访问vmalloc地址空间中的内存。那只是自找麻烦。而且可能非常不安全——其他进程也可以访问吗?写入。

您可能需要再次更新此文件,以便为您的
recv
调用足够的参数。@bdolan:我有点麻烦,必须检查地址是否位于用户空间中。但是,我还想知道为什么不在page表中的supervisor位上进行检查。可能是内核开发人员不希望程序员使用内核缓冲区。(我知道mmap是一种很好的方式。)我使用了这种可怕的方法来分享mem,因为我想快速检查一些东西,并遇到了这个问题。谢谢。@agent.smith,实际上在页面表中查找页面很慢。内核只是检查它是否在用户空间范围内,然后直接访问它(即使在环0中,CPU也会接受不存在或写保护位)。唯一的例外是一些非常早期的386型处理器,在这些处理器中,内核确实会检查页表——但同样,这相当慢。
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);