栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Linux内核模块中实现民意测验

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Linux内核模块中实现民意测验

免责声明

嗯,这是一个很好的体系结构问题,它暗示了有关您的硬件和所需的用户空间接口的一些假设。因此,让我就更改做出结论,并尝试猜测哪种解决方案最适合您的情况。

设计

考虑到您还没有提到

write()
操作,我将进一步假设您的硬件一直在 产生 新数据。如果是这样,您提到的设计可能正是使您感到困惑的地方:

read
调用非常简单。它开始DMA写操作,然后在等待队列中等待。

这正是阻止您以常规,常用(可能是您所希望的)方式使用驱动程序的原因。让我们思考开箱即用,并首先提出所需的用户界面(如何从用户空间使用驱动程序)。在我看来,下一种情况是常用且足够的:

  1. poll()
    您的设备文件以等待新数据到达
  2. read()
    您的设备文件以获得到达的数据

现在,你可以看到,数据请求(以DMA)应该开始

read()
操作。正确的解决方案是连续读取驱动程序中的数据(不从用户空间触发任何数据)并在内部存储,并且当用户要求驱动程序 使用
(通过
read()
操作)数据时,请向用户提供内部存储的数据。如果驱动程序内部没有存储任何数据-用户可以使用
poll()
操作等待新数据到达。

如您所见,这是一个众所周知的生产者-消费者问题。您可以使用循环缓冲区将硬件中的数据存储在驱动程序中(因此,在缓冲区已满时有意丢失旧数据以防止 缓冲区溢出的
情况)。因此,生产者(DMA)写入该RX环形缓冲区的 头部 ,而使用者(用户在

read()
用户空间执行)从该RX环形缓冲区的 尾部
读取。

代码参考

这一切情况让我想起了 串行控制台 [
1,2
]的驱动程序。因此,请考虑在驱动程序实现中使用串行API(如果您的设备实际上
串行控制台)。例如,参见drivers / tty / serial / atmel_serial.c驱动程序。我对UART
API不太熟悉,因此我无法确切告诉您发生了什么,但是乍一看它看起来并不难,因此您可以从该代码中找出一两个问题您的驱动程序设计。

如果您的驱动程序不应该使用串行API,则可以使用下一个驱动程序作为参考:

  • drivers / char / virtio_console.c
  • 驱动程序/char/xillybus/xillybus_core.c

补充

在评论中回答您的问题:

您是否建议在没有可用数据且应阻止时

read
拨打电话?
poll``read

首先,您要决定是否要提供:

  • 阻止I / O
  • 非阻塞I / O
  • 或两者都

让我们假设(出于争论的目的)您想在驱动程序中提供两个选项。在这种情况下,

open()
如果
flags
参数包含
O_NONBLOCK
标志,则应签入呼叫。来自
man2 open

O_NONBLOCK
要么
O_NDELAY

如果可能,以非阻止模式打开文件。

open()
返回的文件描述符的或后续操作都不会导致调用过程等待。有关FIFO(命名管道)的处理,另请参见
fifo(7)
。有关
O_NONBLOCK
与强制性文件锁定和文件租用结合使用的影响的讨论,请参见
fcntl(2)

现在,当您知道用户选择的模式时,可以下一步(在驱动程序中):

  1. 如果
    flags
    in中
    open()
    不包含此类标志,则可以进行阻止
    read()
    (即,如果数据不可用,请等待DMA事务完成,然后返回新数据)。
  2. 但如果
    O_NONBLOCK
    open()
    标志并没有在循环缓冲区可用数据-你应该返回
    read()
    调用与
    EWOULDBLOCK
    错误代码。

来自

man 2 read

EAGAIN
要么
EWOULDBLOCK

文件描述符

fd
引用套接字,并已标记为非阻塞(
O_NONBLOCK
),并且读取将阻塞。POSIX.1-2001允许在这种情况下返回任何一个错误,并且不需要这些常量具有相同的值,因此可移植应用程序应检查这两种可能性。

您可能还想阅读下一篇文章,以更好地了解相应的接口:

[1] POSIX操作系统串行编程指南

[2] 串口编程指南

补充2

我需要某种不断从设备读取数据并填充环形缓冲区的后台任务。

poll
现在是微不足道的-
只需检查该缓冲区中是否有任何东西,但
read
更困难,因为它可能需要等待将某些内容发布到环形缓冲区中。

例如,查看driver / char / virtio_console.c驱动程序的实现。

  1. 在poll()函数中:do
    poll_wait()
    (等待新数据到达)
  2. 在接收数据中断处理程序中:做
    wake_up_interruptible()
    (唤醒
    poll
    read
    操作)
  3. 在read()函数中:
    • 如果端口没有数据:
    • 如果
      O_NONBLOCK
      设置了标志(
      open()
      运行中):立即返回
      -EAGAIN
      =
      -EWOULDBLOCK
    • 否则,我们将阻止读取:执行操作
      wait_event_freezable()
      以等待新数据到达
    • 如果端口有数据:从缓冲区返回数据


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/405822.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号