【问题标题】:fork failures: Cannot allocate memory分叉失败:无法分配内存
【发布时间】:2013-08-24 19:50:43
【问题描述】:

我有一个在 linux 机器上运行的程序。它派生一个发送邮件的进程,并经常记录派生失败消息,指出它无法分配内存。

当我检查常驻内存的大小时,它大约是 12Gb(在这台机器上交换配置为只有 1Gb)。

有没有办法可以确定这块巨大的内存不是泄漏而只是内存增长?

另外,是否有可以调整的系统限制,这样我就不会遇到任何分叉失败?

【问题讨论】:

  • 你想说进程吃光了12GB?机器提供多少内存?机器上设置的内存限制是多少?
  • 我的意思是使用 TOP 命令显示的 RES。这里的系统有 32Gb 作为内存,ulimit 中的最大内存大小显示为无限制。

标签: c linux system fork out-of-memory


【解决方案1】:

我刚刚在嵌入式系统上得到了这个。没有任何限制,df 进程有足够的空闲 RAM,所以这让我很困惑。然后我记得fork() 通过写时复制工作 - 所以在不久的将来子进程可能需要与父进程一样多的 RAM。如果您看到机器据称有大量空闲 RAM,请记住一点 - 它的空闲 RAM 是否至少与调用 fork() 的进程使用的一样多?

【讨论】:

    【解决方案2】:

    要检查内存泄漏,您可能希望在 Valgrind 下运行程序:http://valgrind.org


    要从控制台/shell 获取/设置限制,可以使用 ulimit 命令。

    从程序内部,系统调用getrlimit()/setrlimit() 提供此功能。


    对于由于fork()ing 导致内存紧张的情况,另一种解决方法是立即使用vfork(),然后调用exec*() 系列函数的成员。

    来自man vfork

    vfork()clone(2) 的一个特例。它用于在不复制父进程的页表的情况下创建新进程。它可能在对性能敏感的应用程序中很有用,在这些应用程序中创建一个子级,然后立即发出 execve(2)

    vfork()fork(2) 的不同之处在于父级暂停直到子级终止(通常通过调用 _exit(2),或异常,在传递致命信号后),或者它调用 execve(2)。直到那个 点,孩子与其父母共享所有内存,包括堆栈。子进程不能从当前函数返回或调用exit(3),但可以调用_exit(2)

    【讨论】:

    • 这是信息。 valgrind 没有显示任何重大泄漏,因此它猜测是内存增长。我无法更改程序来设置资源限制,这可以在系统级别使用 ulimit 或类似的东西来完成吗? vfork() 看起来是一种合适的解决方案,但这将再次需要更改代码。
    • @user1032035:有关ulimit的详细说明,请参阅man bash
    猜你喜欢
    • 2015-05-17
    • 2015-09-22
    • 1970-01-01
    • 2013-03-18
    • 1970-01-01
    • 2015-10-21
    • 2016-05-01
    • 2013-02-19
    • 2011-12-12
    相关资源
    最近更新 更多