我想将数据从启用DMA的PCIe硬件设备尽快移入用户空间。
问:如何将“直接I / O通过DMA传输和/或通过DMA传输结合到用户空间”
dma_alloc_coherent
给我可以传递给硬件设备的物理地址。但是将需要设置get_user_pages
并copy_to_user
在传输完成后执行类型调用。这似乎很浪费,要求设备将DMA
DMA到内核内存(充当缓冲区),然后将其再次传输到用户空间。LDD3 p453:/* Only now is it safe to access the buffer, copy to user, etc. */
我理想地想要的是一些内存,该内存可以:
我是否需要使用来映射单页流映射,设置映射和用户空间缓冲区get_user_pages
dma_map_page
?
到目前为止,我的代码是get_user_pages
在用户空间的给定地址上设置的(我称其为直接I /
O部分)。然后,dma_map_page
显示来自的页面get_user_pages
。我给设备返回的值dma_map_page
作为DMA物理传输地址。
我使用一些内核模块作为参考:drivers_scsi_st.c
和drivers-net- sh_eth.c
。我会看infiniband代码,但是找不到最基本的代码!
提前谢谢了。
我现在实际上正在做完全相同的事情,并且正在走ioctl()
路线。一般的想法是让用户空间分配缓冲区,该缓冲区将用于DMA传输,并且ioctl()
将用于将缓冲区的大小和地址传递给设备驱动程序。然后,驱动程序将使用分散收集列表以及流DMA
API来直接与设备和用户空间缓冲区之间来回传输数据。
我正在使用的实现策略是,ioctl()
驱动程序中的进入一个循环,该循环以256k的块(这是硬件对其可处理的分散/聚集条目的硬性限制)的形式进入DMA的用户空间缓冲区。这是隔离在一个函数内部的,该函数在每次传输完成之前都会阻塞(请参阅下文)。当所有字节传输完毕或增量传输函数返回错误时,ioctl()
退出并返回用户空间
的伪代码 ioctl()
/*serialize all DMA transfers to/from the device*/
if (mutex_lock_interruptible( &device_ptr->mtx ) )
return -EINTR;
chunk_data = (unsigned long) user_space_addr;
while( *transferred < total_bytes && !ret ) {
chunk_bytes = total_bytes - *transferred;
if (chunk_bytes > HW_DMA_MAX)
chunk_bytes = HW_DMA_MAX; /* 256kb limit imposed by my device */
ret = transfer_chunk(device_ptr, chunk_data, chunk_bytes, transferred);
chunk_data += chunk_bytes;
chunk_offset += chunk_bytes;
}
mutex_unlock(&device_ptr->mtx);
用于增量传递函数的伪代码:
/*Assuming the userspace pointer is passed as an unsigned long, */
/*calculate the first,last, and number of pages being transferred via*/
first_page = (udata & PAGE_MASK) >> PAGE_SHIFT;
last_page = ((udata+nbytes-1) & PAGE_MASK) >> PAGE_SHIFT;
first_page_offset = udata & PAGE_MASK;
npages = last_page - first_page + 1;
/* Ensure that all userspace pages are locked in memory for the */
/* duration of the DMA transfer */
down_read(¤t->mm->mmap_sem);
ret = get_user_pages(current,
current->mm,
udata,
npages,
is_writing_to_userspace,
0,
&pages_array,
NULL);
up_read(¤t->mm->mmap_sem);
/* Map a scatter-gather list to point at the userspace pages */
/*first*/
sg_set_page(&sglist[0], pages_array[0], PAGE_SIZE - fp_offset, fp_offset);
/*middle*/
for(i=1; i < npages-1; i++)
sg_set_page(&sglist[i], pages_array[i], PAGE_SIZE, 0);
/*last*/
if (npages > 1) {
sg_set_page(&sglist[npages-1], pages_array[npages-1],
nbytes - (PAGE_SIZE - fp_offset) - ((npages-2)*PAGE_SIZE), 0);
}
/* Do the hardware specific thing to give it the scatter-gather list
and tell it to start the DMA transfer */
/* Wait for the DMA transfer to complete */
ret = wait_event_interruptible_timeout( &device_ptr->dma_wait,
&device_ptr->flag_dma_done, HZ*2 );
if (ret == 0)
/* DMA operation timed out */
else if (ret == -ERESTARTSYS )
/* DMA operation interrupted by signal */
else {
/* DMA success */
*transferred += nbytes;
return 0;
}
中断处理程序非常简短:
/* Do hardware specific thing to make the device happy */
/* Wake the thread waiting for this DMA operation to complete */
device_ptr->flag_dma_done = 1;
wake_up_interruptible(device_ptr->dma_wait);
请注意,这只是一种通用方法,最近几周我一直在研究此驱动程序,但尚未进行实际测试。因此,请不要将此伪代码视为福音,并且一定要加倍检查所有逻辑和参数;-)。
问题内容: 谁能解释我, 什么啊 这有什么用途? 如何使用? 为什么我不能定义与之功能相同的新功能? 问题答案: 一个,表示“输入- 输出控制”是一种特定于设备的系统调用。Linux(300-400)中只有几个系统调用,不足以表示设备可能具有的所有独特功能。因此,驱动程序可以定义一个ioctl,它允许用户空间应用程序向其发送订单。但是,ioctl并不是很灵活,并且会变得有些混乱(数十个“魔术数字”
问题内容: 如何使用打开,关闭,ioctl等功能为i2c设备制作字符设备?最近两周我一直在寻找有关它的信息,找不到任何有效的方法。我在Essential LinuxDevice Drivers中找到了一些信息,但是它是针对2.6内核编写的,我使用3.4.79(我正尝试在cubian distr上为cubieboard2编写此驱动程序),因此本书有许多不推荐使用的功能,我试图在那里写我的驱动程序,但
更新时间:2019-04-16 19:04:41 各种不同的设备在不同的操作系统使用时,可能需要单独安装对应的驱动程序。为了方便用户,Hacklab提供了支持的部分开发板串口驱动程序下载及安装信息,请根据使用的开发板和PC OS下载对应的驱动程序。 串口芯片驱动 CP210x 下载地址 使用该串口驱动的开发板包括: ST Nucleo F412ZG esp32devkitc(Board类型可选择E
操作系统其中一个目的就是向用户掩盖系统硬件设备的特殊性。例如,虚拟文件系统呈现了安装的文件系统的一个统一的试图,而和底层的物理设备无关。本章描述 Linux 核心是如何管理系统中的物理设备的。 CPU 不是系统中唯一的智能设备,每一个物理设备都由它自己的硬件控制器。键盘、鼠标和串行口由 SuperIO 芯片控制, IDE 磁盘由 IDE 控制器控制, SCSI 磁盘由 SCSI 控制器控制,等等。
Device Drivers 设备驱动程序 Generic Driver Options 驱动程序通用选项.[提示]Linux Kernel Driver DataBase网 站是搜索驱动程序与硬件型号对应关系的绝佳网站.如果你不知道某个驱动(例如"CONFIG_INTEL_IOATDMA")究竟对应着哪些型号的硬件, 那么可以直接根据该驱动选项的首字母(本例是"I")进入对应的索引页去查找到该驱
问题内容: 我正在尝试打电话 直接,但获得EFAULT错误代码。出现此错误是因为 buf 指向内核空间中的内存。 那么,是否有可能从内核分配用户空间内存? 与 内核内存相似并返回指向内核内存的指针。 问题答案: 您可以使用以下方法临时禁用内存地址有效性检查: