【问题标题】:cat vs. opening a readonly filecat 与打开只读文件
【发布时间】:2016-11-02 15:50:43
【问题描述】:

tl;dr - 当我在做一个无限长文件的猫时,一切都很好,但是当我使用 C 的“打开”即使没有读取同一个文件时,一切都失败了。为什么会发生这种情况?我怎样才能让它不发生?


我正在 Digi ME9210 上进行开发,它以小型嵌入式 linux O/S 为主角,但还有其他有用的东西,例如 SPI 驱动程序。

最终,我想做的是以每秒 10k 个样本的恒定间隔读取 SPI 设备。设备附带的示例 SPI 驱动程序提供了通过使用 ioctl 函数从用户空间读取 SPI 的能力。不幸的是,在查看时间时,读取完全不一致 - usleep 和其他延迟函数给出了不一致的结果,即使我只是使用像 while (true) { sample_spi(); } 这样的紧密循环,间距也是不一致的。

我决定研究一下编辑内核驱动程序。通过编辑适当的寄存器,我可以获得非常可靠的周期性中断,并且我可以设置一个例程,这样我就可以在每次中断时获得甜蜜的 SPI 读数。伟大的。出于调试目的,我说“我也只是看看它是否能以 1kHz 运行,而不是期待完整的 10kHZ”

在 shell 中,为了检查我的时间,我跑了

cat /dev/spidev1.0

进行无限读取。 SPI 读取出来的结果主要是周期性的,偶尔会出现滑动(三到五毫秒而不是 1 毫秒)。我认为这与 cat 实用程序必须定期转储到流有关。所以我写了一个小 C 程序,看起来像这样:

int f = open("/dev/spidev1.0", O_RDONLY); // some time-wasting logic here close(f);

当我运行它时,我可能会读取 10 次 SPI,然后整个 Linux 机器停止响应,直到我进行重置。

这是怎么回事?为什么catting 文件在打开时会导致冻结状态?猫有什么不同?我假设 cat 看起来很像“打开文件,阅读它,打印它,然后关闭它”。 C 代码完成了其中的 50%,甚至还没有完成 50%。

我看过的东西

  1. 也许你的中断实际上是不可持续的 - 如果我只是更新计数器而不是执行 SPI 读取,中断会非常愉快地永远持续下去。
  2. 也许 C 永远不会像 cat 一样工作 - 如果我将中断速度降低到 20Hz,C 代码和 cat 的工作方式将完全一样。
  3. 也许 cat 是完美的 - 如果我将中断速度提高到 10kHz,cat 会在冻结之前读取大约 5ms。在冻结之前,c 代码将执行几次读取,间距大不相同。

【问题讨论】:

  • 您可以查看 cat 的源代码,如果有帮助的话。或者至少是这里可用的 GNU cat 版本 - git.savannah.gnu.org/cgit/coreutils.git/plain/src/cat.c。当然,如果您可以检查您的 linux 版本的 cat 的特定版本的来源,那将是最好的。注意他们使用fdadvise (input_desc, 0, 0, FADVISE_SEQUENTIAL);,也许这很重要。
  • 如果您能够使用您的代码锁定整个内核,我猜您是从错误的角度看待问题:您不需要修复应用程序以像 @987654329 那样工作@,而是您的驱动程序不要锁定机器。
  • 如果不知道您的代码是如何读取的,以及驱动程序可能在做什么(如处理打开、读取、轮询等),将很难提供帮助。正如@tofro 所说,用户态程序不应该锁定内核。
  • 您将其与哪个cat 进行比较?有很多实现。 here's a couple
  • @tofro(和 Hasturkun)- 谢谢,这实际上是一个非常合理的建议,我忽略了。我假设我在用户空间中所做的事情是以某种方式将内核推入未定义状态,但这提出了一个问题,即为什么我让这样的状态存在。在过多地研究 cat 之前,我将开始重新检查内核。

标签: c linux-kernel embedded-linux cat spi


【解决方案1】:

您应该尝试编写自己的类似cat 的程序来测试您的打开、读取和关闭代码。然后将其他处理添加到该程序,直到出现问题。

如果你发现你的cat-like 程序不起作用,那么

从命令行输入:

strace -o spi_cat_trace.txt cat /dev/spidev1.0
less spi_cat_trace.txt

然后尝试找出您的cat 类程序与cat 在读取文件时所做的不同。

【讨论】:

  • 看看实际的cat(1)源代码不是更好吗?
  • 如果您查看cat 的源代码,您会看到很多实际上可能无法执行的代码。您必须对代码所做的决定进行分类,以找出它实际做了什么。使用strace,您可以看到实际发生的情况,而不必担心cat 是如何决定它会发生的。在查看strace 之后,您可能会看到一些令人费解的事情并引导您调查代码。
  • ...但不要看gnu cat,它可能太复杂了。看看BSD cat,它可能更清楚。 FreeBSD cat 只有一个 362 行长的源文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-10
  • 2013-05-02
  • 1970-01-01
  • 1970-01-01
  • 2023-02-12
  • 2011-11-22
  • 1970-01-01
相关资源
最近更新 更多