【问题标题】:bypassing tty layer and copy to user绕过tty层并复制给用户
【发布时间】:2013-09-26 16:08:49
【问题描述】:

我想将数据从内核模块复制到用户空间,该内核模块从串口接收数据并将其传输到 DMA,然后将数据转发到 tty 层,最后到用户空间。

当前流量是 串口驱动FIFO--> DMA-->TTY层-->用户空间(到tty层的数据在定时器到期时从DMA清空)

我想要达到的是

串行驱动FIFO-->DMA-->用户空间。 (我可以使用计时器将数据发送到用户空间,如果有更好的方法请告诉我)

处理serialFIFO->DMA的内核模块也不是字符设备。 我想完全绕过 tty 层。实现这一目标的最佳方法是什么?

任何指针/代码 sn-p 将不胜感激。

【问题讨论】:

  • 我个人会首先为另一个具有类似要求的设备寻找驱动程序,例如用于嵌入式系统上的同步串行通道的驱动程序(只要确保它适用于普通的 linux,而不是uClinux内核,可以使用某些快捷方式)。
  • 嗨,克里斯,感谢您的 cmets,它适用于基于 MontaVista (2.6.32) 的嵌入式 linux。我找了一个这样的例子,但没有找到。关于使用基于 mmap 的驱动程序将数据传递到用户空间的任何想法。我一直在思考以下路径。驱动程序会将数据复制到 DMA,然后从 DMA 将数据复制(memcpy)到基于 mmap 的内存,用户空间程序可以从中读取数据。我也担心这种方法的一些问题。即如何通知用户空间有新数据并避免数据被 DMA 覆盖/损坏。
  • "is not a character device" -- 那么它必须是一个block 设备,这没有意义。 "...并将其传输到 DMA" -- DMA 是一种传输数据的方法,而不是复制的目的地。请解释您认为绕过 tty 层的好处是什么。你明白你放弃了什么吗? tc[gs]etattr() 和朋友?这可能是一个 XY 问题。您是否正在尝试减少延迟?请参阅使用 ASYNC_LOW_LATENCY 解决的 question

标签: linux-kernel serial-port linux-device-driver mamp dma


【解决方案1】:

在 >=3.10.5 中,您所指的“串行 FIFO”称为uart_port。这些在drivers/tty/serial 中定义。

我假设您想要做的是将 UART 的驱动程序复制到一个新文件中,然后不是使用 uart_insert_char 从 UART RX FIFO 插入字符,而是要将字符插入到缓冲区中您可以从用户空间访问。

这样做的方法是创建第二个驱动程序,一个具有文件操作的misc类设备驱动程序,包括mmap,并分配驱动程序的mmap文件操作函数与用户空间相关联的内核内存映射内存。 Maxime Ripard为此编写了good example的代码。此示例是为 FIQ 处理的设备编写的,但您可以仅使用探测例程的 dma_zalloc_coherent 调用和 mmap 例程,以及它对 remap_pfn_range 的调用,来实现这一目的,即将用户空间 mmap 关联到分配内存的misc 设备文件。

如果您的 misc 驱动程序,您需要使用全局 void 指针或使用导出符号将您在 misc 驱动程序中分配的内存连接到您在 UART 驱动程序中写入的缓冲区是一个模块。在 UART 驱动程序中初始化指向一个已知无效值的指针并对其进行测试,以确保 misc 驱动程序已分配它,然后再尝试将字符插入它指向的地址。

请注意,您不能直接将mmap 函数添加到UART 驱动程序,因为UART 驱动程序类不支持mmap 文件操作。它只支持include/linux/serial_core.hstruct uart_ops中定义的操作。

诚然,这是一个麻烦的解决方案 - 两个 设备驱动程序,但另一种方法是编写一个新的设备类,一个具有mmap 操作的 UART 设备,这将是很多与上述解决方案相比,虽然它会很优雅。迄今为止没有人这样做,因为正如 Jonathan Corbet 所说的 "...not every device lends itself to the mmap abstraction; it makes no sense, for instance, for serial ports and other stream-oriented devices",尽管这正是您所要求的。

我根据mxs-auart.c 代码和Maxime 的示例为轮询模式UART 驱动程序实现了这个解决方案。这不是微不足道的努力,但主要是因为我正在为轮询计时器使用 FIQ 处理程序。您应该留出两到三周的时间来让整个系统启动并运行起来。

您问题的 DMA 方面取决于 UART 是否支持 DMA 传输模式。如果是这样,那么您应该可以使用序列号flags 进行设置。 i.MX28 的 PrimeCell auarts 支持 DMA 传输,但对于我的应用程序而言,直接从 UART RX FIFO 读取字节并没有优势。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-05
    • 1970-01-01
    • 2016-06-21
    • 2018-11-13
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多