草庐IT

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

coder 2023-06-17 原文

我有一个简单的字符设备驱动程序,可让您从自定义硬件设备中读取。它使用DMA将数据从设备内存复制到内核空间(然后由用户决定)。
read调用非常简单。它开始DMA写操作,然后在等待队列中等待。 DMA完成后,中断处理程序将设置一个标志并唤醒等待队列。需要注意的重要一点是,即使在设备要提供数据之前,我也可以随时启动DMA。 DMA引擎将坐下等待,直到有要复制的数据为止。这很好。我可以在用户空间中实现一个简单的阻塞读取调用,它的行为与我期望的一样。

我想实现poll,以便可以在用户空间中使用select系统调用,从而可以同时监视此设备和套接字。

我可以在poll上找到的大多数resources都说:

  • 为每个等待队列调用poll_wait,这可能表明
  • 状态发生了变化
  • 返回一个位掩码,指示数据是否可用

  • 第二部分使我感到困惑。我见过的大多数示例都有一种简单的方法(指针比较或状态位)来检查数据是否可用。就我而言,除非启动DMA,否则数据将永远不可用,即使执行了此操作,数据也不会立即可用(在设备实际拥有数据并完成DMA之前可能要花费一些时间)。

    那将如何实现呢? poll函数是否应该实际启动DMA,以便最终获得数据?我想这会破坏我的read函数。

    最佳答案

    免责声明

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

    设计

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

    The read call is very simple. It starts a DMA write, and then waits on a wait queue.



    这正是阻止您以常规,常用(可能是您所希望的)方式使用驱动程序的原因。让我们思考开箱即用的情况,并首先提出所需的用户界面(如何从用户空间使用驱动程序)。在我看来,下一种情况是常用且足够的:
  • poll()您的设备文件以等待新数据到达
  • read()您的设备文件以获得到达的数据

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

    如您所见,这就是众所周知的producer-consumer problem。您可以使用circular buffer将来自硬件的数据存储在驱动程序中(因此,在缓冲区已满时有意丢失旧数据以防止缓冲区溢出的情况)。因此,生产者(DMA)写入该RX环形缓冲区的,而消费者(用户在用户空间中执行read())从该RX环形缓冲区的读取。

    代码引用

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

    如果您的驱动程序不应该使用串行API,则可以使用下一个驱动程序作为引用:
  • drivers/char/virtio_console.c
  • drivers/char/xillybus/xillybus_core.c

  • 补充

    在评论中回答您的问题:

    are you suggesting that read calls poll when there is no data available and read should block?



    首先,您要决定是否要提供:
  • 阻止I/O
  • non-blocking I/O
  • 或两者都

  • 让我们假设(出于争论的目的)您想在驱动程序中同时提供这两个选项。在这种情况下,如果open()参数包含flags标志,则应 checkin O_NONBLOCK调用。从 man 2 open :

    O_NONBLOCK or O_NDELAY

    When possible, the file is opened in nonblocking mode. Neither the open() nor any subsequent operations on the file descriptor which is returned will cause the calling process to wait. For the handling of FIFOs (named pipes), see also fifo(7). For a discussion of the effect of O_NONBLOCK in conjunction with mandatory file locks and with file leases, see fcntl(2).



    现在,当您知道用户选择的模式时,可以下一步(在驱动程序中):
  • 如果flags中的open()不包含此类标志,则可以阻止read()(即,如果数据不可用,请等待DMA事务完成然后返回新数据)。
  • 但是,如果O_NONBLOCK标志中有open(),并且循环缓冲区中没有可用数据,则应从read()调用返回,并返回EWOULDBLOCK错误代码。

  • man 2 read :

    EAGAIN or EWOULDBLOCK

    The file descriptor fd refers to a socket and has been marked nonblocking (O_NONBLOCK), and the read would block. POSIX.1-2001 allows either error to be returned for this case, and does not require these constants to have the same value, so a portable application should check for both possibilities.



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

    [1] Serial Programming Guide for POSIX Operating Systems

    [2] Serial Programming HOWTO

    补充2

    I need some sort of background task that is continuously reading from the device and populating the ring buffer. poll is now trivial - just check if there's anything in that buffer, but read is more difficult because it may need to wait for something to be posted to the ring buffer.



    例如,查看drivers/char/virtio_console.c驱动程序实现。
  • poll()函数中:执行poll_wait()(以等待新数据到达)
  • receive data interrupt handler中:执行wake_up_interruptible()(唤醒pollread操作)
  • read()函数中:
  • ,如果端口has no data:
  • (如果设置了O_NONBLOCK标志)(在open()操作中):立即返回-EAGAIN = -EWOULDBLOCK
  • 否则我们将阻止读取:执行wait_event_freezable()以等待新数据到达
  • (如果端口有数据):返回data from buffer


  • 另请参阅相关问题:How to add poll function to the kernel module code?

    关于linux - 在Linux内核模块中实现民意测验,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34027366/

    有关linux - 在Linux内核模块中实现民意测验的更多相关文章

    1. ruby - 在 Ruby 中使用匿名模块 - 2

      假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

    2. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

      作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

    3. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

      我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

    4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

      我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

    5. ruby - 当使用::指定模块时,为什么 Ruby 不在更高范围内查找类? - 2

      我刚刚被困在这个问题上一段时间了。以这个基地为例:moduleTopclassTestendmoduleFooendend稍后,我可以通过这样做在Foo中定义扩展Test的类:moduleTopmoduleFooclassSomeTest但是,如果我尝试通过使用::指定模块来最小化缩进:moduleTop::FooclassFailure这失败了:NameError:uninitializedconstantTop::Foo::Test这是一个错误,还是仅仅是Ruby解析变量名的方式的逻辑结果? 最佳答案 Isthisabug,or

    6. ruby - 获取模块中定义的所有常量的值 - 2

      我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

    7. ruby - 模块嵌套代码风格偏好 - 2

      我的假设是moduleAmoduleBendend和moduleA::Bend是一样的。我能够从thisblog找到解决方案,thisSOthread和andthisSOthread.为什么以及什么时候应该更喜欢紧凑语法A::B而不是另一个,因为它显然有一个缺点?我有一种直觉,它可能与性能有关,因为在更多命名空间中查找常量需要更多计算。但是我无法通过对普通类进行基准测试来验证这一点。 最佳答案 这两种写作方法经常被混淆。首先要说的是,据我所知,没有可衡量的性能差异。(在下面的书面示例中不断查找)最明显的区别,可能也是最著名的,是你的

    8. ruby-on-rails - 如何在 Ruby on Rails 中实现无向图? - 2

      我需要在RubyonRails中实现无向图G=(V,E)并考虑构建一个Vertex和一个Edge模型,其中Vertex有_多条边。由于边恰好连接两个顶点,您将如何在Rails中执行此操作?您是否知道任何有助于实现此类图表的gem或库(对重新发明轮子不感兴趣;-))? 最佳答案 不知道有任何现有库在ActiveRecord之上提供图形逻辑。您可能必须实现自己的Vertex、EdgeActiveRecord支持的模型(请参阅Rails安装的rails/activerecord中的vertex.rb和edge.rb/test/fixtur

    9. ruby-on-rails - 使用 config.threadsafe 时从 lib/加载模块/类的正确方法是什么!选项? - 2

      我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co

    10. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

      按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

    随机推荐