【发布时间】:2019-05-24 08:37:22
【问题描述】:
我的实时系统有一点分页问题,我想知道 linux 在我的特定情况下应该如何表现。
除其他外,我的应用程序使用 pthread_create() 生成 2 个线程,它们在一组共享缓冲区上运行。 第一个线程,我们称之为 A,从设备读取数据,对其执行一些计算,并将结果写入其中一个缓冲区。 一旦该缓冲区已满,线程 B 将读取所有结果并通过以太网将它们发送到 PC,而线程 A 将写入下一个缓冲区。
我注意到,每次线程 A 开始写入以前未使用的缓冲区时,我都会错过一些中断并丢失数据(每个数据包的标头中有一个 id,如果增加超过 1,我错过了中断)。 因此,如果我使用 n 个缓冲区,我会在数据采集开始时得到恰好 n 次错过的中断(因此问题肯定是由分页引起的)。
为了解决这个问题,我在所有缓冲区上使用了 mlock() 和 memset() 以确保它们实际被分页。 这解决了我的问题,但我想知道我的代码中的哪个位置是正确的。在我的主应用程序中,还是在一个/两个线程中? (目前我在两个线程中都这样做)
根据 libc 文档(第 3.4.2 节“锁定的内存详细信息”),使用 fork() 创建的子进程不会继承内存锁。 那么pthreads呢?它们的行为方式是否相同,或者它们会从我的主进程继承这些锁?
关于我的系统的一些背景信息,尽管我认为这在这种特殊情况下并不重要:
- 它是一个嵌入式系统,由具有双核 Cortex-A9 的 SoC 提供支持,运行具有 PREEMPT_RT 的 Linux 4.1.22。
- 中断频率为4kHz
- 线程优先级(如 htop 所示)为中断的 -99,线程 A 的 -98(这两者都高于所有其他中断的标准优先级 -51)和线程 B 的 -2李>
编辑:
我做了一些额外的测试,从不同的线程(和主线程)调用我的页面锁定函数。
如果我将页面锁定在 main() 中,然后尝试再次将它们锁定在其中一个线程中,我希望看到 main() 出现大量页面错误,但线程本身没有页面错误(因为页面应该已经被锁定)。然而,htop 讲述了一个不同的故事:我看到每个锁定这些页面的线程都有大量的页面错误(MNFLT 列)。
对我来说,这表明 pthread 实际上确实具有与使用 fork() 生成的子进程相同的限制。如果是这种情况,将它们锁定在两个线程中(但不在主线程中)将是正确的过程。
【问题讨论】:
-
线程使用相同的地址空间和页表,所以锁应该是通用的。
-
看来他们不是...我已将我的新发现添加到我的初始帖子中
-
请显示主线程和线程的锁调用。您确定使用相同的地址吗?
-
好的,所以我尝试为我的问题创建一个简化的最小示例,并且该示例的行为完全符合应有的要求。我还检查了我实际应用程序上的地址,但它们对于所有线程来说绝对是相同的。我不知道这是怎么发生的,因为我从来没有解锁任何页面(所以我的应用程序的行为应该与最小示例完全相同)。当然,我的应用程序要大得多,无论是在代码大小还是内存消耗方面,但这不应该影响任何这些
-
锁定 main 后,你确定线程中的页面错误不是来自被分页的代码吗?