我使用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个字节,但它不会以任何方式发出段错误信号。
答案 0 :(得分:7)
RLIMIT_DATA
描述了进程数据段的最大大小。传统上,分配内存的程序通过调用brk()
来扩大数据段,以便从操作系统中分配内存。
Go不使用这种方法。相反,它使用mmap()
系统调用的变体来请求地址空间中任何位置的内存区域。这比基于brk()
的方法灵活得多,因为您可以使用munmap()
释放任意内存区域,而基于brk()
的方法只能从数据段的末尾解除分配内存。 / p>
结果是RLIMIT_DATA
无法控制进程使用的内存量。请尝试使用RLIMIT_AS
,但要注意此限制还包含用于文件映射的地址空间,尤其是在共享库的情况下。