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

gga*_*ngg 4 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
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的考验.

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")
    }
}
Run Code Online (Sandbox Code Playgroud)

这是备忘录:

package main

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

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

fuz*_*fuz 8

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

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

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