问题:
假设我创建了一个cgroup,并将200MB的内存限制附加到该cgroup上。然后我在cgroup内运行一个内存密集型进程,并使用完了它的200MB限制。
在进程运行时,是否可以降低进程的内存消耗?也就是说,当进程已经在使用200MB时,我能否将其限制设置为100MB?如果可以,内核会多快释放cgroup使用的100MB内存,并且如果进程尝试访问该内存会发生什么?
分析
cgroup的作用原理如下:
1.创建cgroup:首先,你需要创建一个cgroup,这是一个用于管理一组相关进程的容器。
2.分配进程到cgroup:将你希望限制的进程分配到所创建的cgroup中。这可以通过将进程的PID写入cgroup的cgroup.procs文件来完成。
3.设置资源限制:接下来,你可以在cgroup中设置资源限制。例如,你可以通过将内存限制写入memory.limit_in_bytes文件来限制进程组的内存使用。
4.资源监控和调整:一旦进程组被分配到cgroup并设置了资源限制,内核会监视进程组的资源使用情况。当进程组的资源使用超过限制时,内核会采取相应的措施来调整资源使用。
对于内存限制的例子,如果你将一个进程通过cgroup限制为200MB的内存使用,以下是cgroup如何发挥作用的:
1.内存限制设置:你将200MB的内存限制写入cgroup的memory.limit_in_bytes文件。
2.内核监控:内核会定期检查进程组的内存使用情况。一旦发现进程组的内存使用超过了限制,内核会采取措施来限制内存使用。
3.限制内存分配:当进程组的内存使用超过限制时,内核会禁止进程组继续分配额外的内存。这意味着进程组无法通过动态分配内存来超出限制。
4.内存回收:内核会通过回收进程组使用的内存页来释放内存。这包括丢弃磁盘缓存页和将匿名内存(未关联到文件的内存)换出到交换空间。
5.进程终止:如果进程组的内存使用持续超过限制,并且内存回收无法满足要求,内核可能会选择终止进程组中的某些进程,以减少内存使用。
问题答案
当你在cgroup中运行一个进程并设置了内存限制时,内核会根据限制来管理进程的内存使用。如果你尝试将限制从200MB降低到100MB,内核会根据新的限制进行调整。
当内核检测到进程的内存使用超过新的限制时,它会开始通过以下方式降低内存消耗:
1.释放磁盘缓存页面:内核会丢弃一些在磁盘缓存中的页面,因为这些页面可以在需要时重新加载。
2.交换匿名内存:如果系统启用了交换空间,内核可以将一部分匿名内存(不与磁盘上的文件关联的内存)交换到交换空间中,从而释放物理内存。
这样,内核会逐渐释放超过新限制的内存,直到进程的内存使用符合新的限制。
需要注意的是,如果内核无法将进程的内存使用降到新的限制以下(例如由于没有可用的交换空间),则可能会发生错误或触发OOM(Out of Memory)机制,导致进程被终止。
当涉及到内存限制和OOM(Out of Memory)时,还有两个与cgroup相关的重要参数:memory.soft_limit_in_bytes和oom_control。
1.memory.soft_limit_in_bytes:这个参数用于设置内存软限制,它不会触发OOM killer机制。当系统面临内存压力时,内核可以使用软限制来确定哪些进程首先进行页面交换,以释放内存。软限制可以帮助在不终止进程的情况下,通过页面交换来减少内存使用。
2.oom_control:这个参数用于控制OOM killer的行为。OOM killer是内核的一种机制,用于在内存不足时选择终止进程以释放内存。oom_control参数允许你设置在发生OOM事件时的处理方式。你可以选择让OOM killer终止进程(默认行为),或者你可以通过设置oom_control来暂停进程而不终止它们,以便稍后处理。
通过设置oom_control参数为"1",你可以暂停cgroup中的进程,从而避免OOM killer的终止行为。这样,你就可以在进程达到内存限制时暂时停止它们,然后手动处理内存问题,例如增加内存限制或终止其他进程。
这两个参数提供了更灵活的内存管理和OOM处理机制,使你能够更好地控制进程组的行为和系统的稳定性。
参考资料: