C++ 实时应用中使用mlockall()的最佳方式(纳秒敏感)

C++ 实时应用中使用mlockall()的最佳方式(纳秒敏感),c++,linux,operating-system,system,C++,Linux,Operating System,System,我正在阅读mlockall()的手册页: 它提到 Real-time processes that are using mlockall() to prevent delays on page faults should reserve enough locked stack pages before entering the time- critical section, so that no page fault can be caused by function calls. This

我正在阅读mlockall()的手册页:

它提到

Real-time processes that are using mlockall() to prevent delays on page 
faults should reserve enough locked stack pages before entering the time-
critical section, so that no page fault can be caused by function calls.  This 
can be achieved by calling a function that allocates a sufficiently large 
automatic variable (an array) and writes to the memory occupied by this array in 
order to touch these stack pages.  This way, enough pages will be mapped for the 
stack and can be locked into RAM.  The dummy writes ensure that not even copy-
on-write page faults can occur in the critical section.
我对这种说法有点困惑:

This can be achieved by calling a function that allocates a sufficiently large 
automatic variable (an array) and writes to the memory occupied by this array in 
order to touch these stack pages.
调用函数时,所有自动变量(堆栈上的变量)都会在堆栈上“动态”创建。那么,我如何才能实现上一句话所说的

例如,假设我有这个函数:

void foo() {
char a;
uint16_t b;
std::deque<int64_t> c;
// do something with those variables
}
如果是的话,如果我先在heap上分配stackPage变量,然后写入,然后释放,会有什么不同吗?可能是的,因为堆和堆栈是RAM中的两个不同区域

上面提到的deque只是为了提出另一个相关的问题——如果我想为使用堆栈页和堆页的东西保留内存怎么办。调用reserveStackPages()的“heap”版本会有帮助吗

我们的目标是最小化应用程序中的所有抖动(是的,我知道还有很多其他方面需要考虑,比如TLB未命中等;只是尝试一次处理一种抖动,然后慢慢地进入所有抖动)

提前谢谢


注:这适用于低延迟交易应用程序(如果有必要)。

您通常不需要使用
mlockall
,除非您编写(或多或少硬的)实时应用程序(我实际上从未使用过)

如果您确实需要它,最好使用C(而不是真正的C++)编写代码,这是代码中最实时的部分,因为您肯定想了解内存分配的细节。请注意,除非您深入研究
std::deque
实现,否则您并不确切知道它位于何处(可能大多数数据都是堆分配的,即使
c
是堆)

您应该首先详细了解进程的虚拟地址空间。对于这一点,它很有用:从流程内部,您将阅读
/proc/self/maps
(请参阅),从外部(例如某个终端),您将对pid 1234流程执行
cat/proc/1234/maps
。或使用

因为堆和堆栈是RAM中的两个不同区域

事实上,您的进程的地址空间包含许多段(在
/proc/1234/maps
中列出),远远不止两段。通常,每个动态链接的共享库(例如
libc.so
)都会带来一些片段

在终端中尝试
cat/proc/self/maps
cat/proc/$$/maps
,以更好地了解虚拟地址空间。在我的机器上,第一个给出了
cat
过程的19个段(每个段显示为一行),第二个给出了
zsh
(我的shell)过程的97个段

为了确保堆栈有足够的空间,您确实可以调用一个分配足够大的自动变量的函数,比如
reserveStackPages
。请注意,调用堆栈的大小实际上是有限的(通常只有几兆字节,另请参阅)

如果你真的需要<代码> MyLoCuel(这是不可能的),你可以考虑静态链接你的程序(在你的虚拟地址空间中有更少的段)。 再看看(也许吧)。它通常比

mlockall
有用得多。顺便说一句,在实践中,大多数虚拟内存都在RAM中(除非您的系统进行了实验,然后您会立即看到它)

也可以阅读,以了解的作用


PS.纳秒敏感应用程序没有多大意义(因为软件无法控制)。

您正在编写哪种应用程序?请编辑您的问题以解释这一点。是否确实要
mlockall
?即使进行了编辑,您也没有解释要编写的应用程序类型。“实时”并不意味着什么。是网络过滤器,还是机器人视觉程序?nano second sensitive没有任何意义,而且肯定是一种错觉(因为缓存未命中)。我最终否决了你的问题,因为你仍然没有给出足够的上下文,也没有解释你正在编写什么样的应用程序。当你解释的时候,我会回复我的否决票。哈哈,是的,纳秒实际上没有多大意义。但我试图做的是尽量减少应用程序延迟方面的不安。一些正在工作的应用程序被迁移到FPGA中,以避免所有的抖动。这应该是一个问题,您仍然需要解释您正在编写什么样的应用程序。纳秒级敏感和C++容器不兼容。是的,使用C++容器可能会触发抖动(因为它是特定于实现的,并且可能使用堆来分配元素)。我特意把它放在那里,以便我想看看人们是如何考虑将mlockall()用于堆栈上的容器的,因为容器将使用堆栈页以及(可能)堆页。
void reserveStackPages() {
int64_t stackPage[4096/8 * 1024 * 1024];
memset(stackPage, 0, sizeof(stackPage));
}