2010-09-06 78 views
0

我使用Linux for ARM处理器进行线缆调制解调器。我写了一个工具,它使用原始套接字发送/暴发定制的UDP数据包。我从零开始构建数据包,以便我们可以灵活地使用不同的选项。这个工具主要用于压力测试路由器。子进程的内存优化

我实际上已经创建了多个接口。每个接口将使用DHCP获取IP地址。这是为了使调制解调器像虚拟客户端设备(vcpe)一样工作。

当系统启动时,我启动要求的那些进程。我开始的每个过程都会不断发送数据包。因此进程0将使用接口0发送数据包等。每个发送数据包的进程都允许进行配置(在运行时更改UDP参数和其他选项)。这就是我决定分开处理的原因。

我使用fork和excec从调制解调器的调配过程开始这些过程。

现在的问题是每个进程占用大量内存。只启动3个这样的进程,导致系统崩溃并重启。

我曾尝试以下:

我一直认为推动更多的代码共享库会有所帮助。所以当我尝试将许多函数移动到共享库中并在进程中保留最小代码时,我感到意外并没有什么区别。我还删除了所有数组,并使它们使用堆。但它没有区别。这可能是因为进程持续运行,如果它是堆栈或堆没有区别?我怀疑我从哪里调用fork的过程是巨大的,这就是我使得结果很大的过程的原因。我不知道我还能如何去做。说过程A是巨大的 - >我通过分叉和excec来启动过程B. B继承了A的内存区域。所以,现在我这样做 - > A启动C,它启动B也不会帮助,因为C仍然继承A ?.我用vfork作为一种替代方法,也没有帮助。我想知道为什么。

如果有人给我提示,以帮助我减少每个独立子进程使用的内存,我将不胜感激。

回答

2

鉴于这是一个测试工具,那么最有效的做法是向测试机器添加更多内存。

做不到这一点:

  1. 您如何测量内存使用情况?有些方法无法获得准确的结果。
  2. 检查你没有任何内存泄漏。例如在Linux x86上使用Valgrind。
  3. 你可以尝试在单个进程中运行不同的测试器,因为不同的线程,甚至在一个线程中复用 - 因为网络应该是限制因素?
  4. 当新的执行得到一个新的内存映射时,exec()会缩小进程的内存大小。
  5. 如果你不能添加物理内存,那么也许你可以添加交换,也许只是为了测试?
1

技术上不回答你的问题,但提供了几个备选解决方案:如果你有考虑过使用pktgen使用Linux

?它是一种灵活的工具,可以尽可能快地从内核发送UDP数据包。这比用户空间工具快得多。

哦,一个无耻的插头。我制作了一个multi-threaded network testing tool,它可以用来通过UDP数据包发送垃圾邮件。它可以以多进程模式(通过使用fork)或多线​​程模式(使用pthread)运行。 pthreads可能会使用更少的RAM,所以对您来说可能会更好。如果有什么值得一看的话,我可以花多年的时间来改进这个代码,并且它能够生成足够的数据包来饱和一个10Gbps的接口。

1

可能发生的情况是进程A中的fork调用需要大量的RAM + swap(如果有)。因此,当你从这个进程调用fork()时,内核必须为子进程保留足够的RAM和交换,以便拥有它自己的父进程的可写私有内存副本(实际上是写时拷贝),即堆栈和堆。当您从子进程调用exec()时,不再需要该内存,并且您的子进程可以拥有它自己的较小的私有工作集。

因此,首先要确定的是,在fork()和exec()之间的状态中,一次没有多个进程。在此状态期间,子进程必须具有其父进程虚拟内存空间的副本。

其次,尝试使用overcommit设置,这将允许内核保留比实际存在更多的内存。这些是/ proc/sys/vm/overcommit *。你可以放弃使用overcommit,因为你的子进程只需要额外的虚拟机空间,直到他们调用exec,并且实际上不应该触及父进程的重复地址空间。

第三,在您的父进程中,您可以使用共享内存而不是堆栈或堆来分配最大的块,这些块是私有的。因此,当你分叉时,这些共享内存区域将与子进程共享,而不是重复写时拷贝。