子进程的内存优化

时间:2010-09-06 12:37:42

标签: c linux memory process

我在Linux上使用ARM处理器进行电缆调制解调器。我编写了一个工具,使用原始套接字发送/编译定制的UDP数据包。我从头开始构建数据包,以便我们可以灵活地使用不同的选项。该工具主要用于压力测试路由器。

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

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

我使用fork启动这些进程,并且从调制解调器的配置过程开始。

现在的问题是每个进程占用大量内存。仅启动3个此类进程会导致系统崩溃并重新启动。

我尝试了以下内容:

我一直认为将更多代码推送到共享库会有所帮助。因此,当我尝试将许多函数移动到共享库中并在进程中保留最少的代码时,我的意外没有任何区别。我还删除了所有数组并使它们使用堆。然而它没有任何区别。这可能是因为进程连续运行,如果是堆栈或堆,它没有任何区别?我怀疑我称之为fork的过程是巨大的,这就是我使结果变得庞大的过程的原因。我不知道我还能怎么做。说过程A很大 - >我通过forking和excec开始进程B. B继承了A的内存区域。所以现在我这样做 - > A开始C开始B也没有帮助,因为C仍继承A?。我使用vfork作为替代方案,但也没有帮助。我不知道为什么。

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

3 个答案:

答案 0 :(得分:2)

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

失败:

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

答案 1 :(得分:1)

在技术上并没有回答你的问题,而是提供了几种替代解决方案:

如果您使用Linux,您是否考虑过使用pktgen?它是一种灵活的工具,可以像接口允许的那样快速地从内核发送UDP数据包。这比用户空间工具快得多。

哦,一个无耻的插头。我制作了一个multi-threaded network testing tool,可用于通过UDP数据包向网络发送垃圾邮件。它可以在多进程模式(通过使用fork)或多线​​程模式(通过使用pthreads)中运行。 pthreads可能会使用更少的RAM,因此可能更适合您使用。如果有什么东西可能值得查看源代码,因为我花了很多年时间来改进这个代码,并且它能够生成足够的数据包以使10gbps接口饱和。

答案 2 :(得分:1)

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

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

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

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