【发布时间】: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%。
我看过的东西
- 也许你的中断实际上是不可持续的 - 如果我只是更新计数器而不是执行 SPI 读取,中断会非常愉快地永远持续下去。
- 也许 C 永远不会像 cat 一样工作 - 如果我将中断速度降低到 20Hz,C 代码和 cat 的工作方式将完全一样。
- 也许 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