sup*_*esk 18 c linux fork linux-kernel
我有一个系统,其中运行两个相同的进程(让我们称之为副本).发出信号时,副本将使用该fork()调用复制自身.第三个进程选择一个进程随机杀死,然后发信号通知另一个进程以创建替换进程.在功能上,该系统运作良好; 它可以整天杀死/重生复制品,除了性能问题.
该fork()呼叫需要的时间越来越长.以下是仍然显示问题的最简单设置.时间显示在下图中:
副本的代码如下:
void restartHandler(int signo) {
// fork
timestamp_t last = generate_timestamp();
pid_t currentPID = fork();
if (currentPID >= 0) { // Successful fork
if (currentPID == 0) { // Child process
timestamp_t current = generate_timestamp();
printf("%lld\n", current - last);
// unblock the signal
sigset_t signal_set;
sigemptyset(&signal_set);
sigaddset(&signal_set, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &signal_set, NULL);
return;
} else { // Parent just returns
waitpid(-1, NULL, WNOHANG);
return;
}
} else {
printf("Fork error!\n");
return;
}
}
int main(int argc, const char **argv) {
if (signal(SIGUSR1, restartHandler) == SIG_ERR) {
perror("Failed to register the restart handler");
return -1;
}
while(1) {
sleep(1);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
系统运行的时间越长,它就越糟糕.
很抱歉没有具体的问题,但有没有人知道发生了什么?在我看来,内核中存在资源泄漏(因此是linux内核标记),但我不知道从哪里开始查找.
我尝试过的:
/proc/<pid>/maps 没有增长.任何提示?我可以提供哪些帮助?谢谢!
速度减慢是由匿名 vmas 的累积引起的,并且是一个已知问题。当有大量fork()调用并且父进程在子进程之前退出时,问题就很明显。以下代码重现了该问题(来源 Daniel Forrest):
#include <unistd.h>
int main(int argc, char *argv[])
{
pid_t pid;
while (1) {
pid = fork();
if (pid == -1) {
/* error */
return 1;
}
if (pid) {
/* parent */
sleep(2);
break;
}
else {
/* child */
sleep(1);
}
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
anon_vma该行为可以通过签入来确认/proc/slabinfo。
有一个补丁(源代码)将复制的长度限制anon_vma_chain为五个。我可以确认该补丁修复了问题。
至于我最终是如何发现问题的,我最终开始printk在整个fork代码中进行调用,检查 中显示的时间dmesg。最终我发现是通话时间anon_vma_fork越来越长。然后就是谷歌搜索的快速问题。
这花了相当长的时间,所以我仍然感谢任何关于更好的方法来追踪问题的建议。对于所有已经花时间试图帮助我的人,谢谢你们。
| 归档时间: |
|
| 查看次数: |
915 次 |
| 最近记录: |