如何在Golang中为进程设置内存限制

时间:2014-07-02 04:07:28

标签: unix memory go

我使用syscall prlimit设置资源限制来处理,它适用于限制CPU时间但是当测试内存使用时,我遇到了问题。

package sandbox

import (
    "syscall"
    "unsafe"
)

func prLimit(pid int, limit uintptr, rlimit *syscall.Rlimit) error {
    _, _, errno := syscall.RawSyscall6(syscall.SYS_PRLIMIT64, uintptr(pid), limit, uintptr(unsafe.Pointer(rlimit)), 0, 0, 0)
    var err error
    if errno != 0 {
        err = errno
        return err
    } else {
        return nil
    }
}

这是我的考验。

func TestMemoryLimit(t *testing.T) {
    proc, err := os.StartProcess("test/memo", []string{"memo"}, &os.ProcAttr{})
    if err != nil {
        panic(err)
    }
    defer proc.Kill()
    var rlimit syscall.Rlimit
    rlimit.Cur = 10
    rlimit.Max = 10 + 1024
    prLimit(proc.Pid, syscall.RLIMIT_DATA, &rlimit)
    status, err := proc.Wait()
    if status.Success() {
        t.Fatal("memory test failed")
    }
}

这是备忘录:

package main

func main() {
    var a [10000][]int
    for i := 0; i < 1000; i++ {
        a[i] = make([]int, 1024)
    }
}

我制作了大量内存并且只为内存设置了10个字节,但它不会以任何方式发出段错误信号。

1 个答案:

答案 0 :(得分:7)

RLIMIT_DATA描述了进程数据段的最大大小。传统上,分配内存的程序通过调用brk()来扩大数据段,以便从操作系统中分配内存。

Go不使用这种方法。相反,它使用mmap()系统调用的变体来请求地址空间中任何位置的内存区域。这比基于brk()的方法灵活得多,因为您可以使用munmap()释放任意内存区域,而基于brk()的方法只能从数据段的末尾解除分配内存。 / p>

结果是RLIMIT_DATA无法控制进程使用的内存量。请尝试使用RLIMIT_AS,但要注意此限制还包含用于文件映射的地址空间,尤其是在共享库的情况下。