Skip to main content
 首页 » 操作系统

Linux Cgroup内核文档翻译(5)——Documentation/cgroup-v1/freezer-subsystem.txt—进程冻结

2022年07月19日57TianFang

  cgroup freezer可用于批处理作业管理系统,该系统启动和停止任务集,以便根据系统管理员的需求来调度机器的资源。 这种程序通常用于HPC群集,以计划对整个群集的访问。 cgroup freezer使用cgroup来描述要由批处理作业管理系统启动/停止的任务集。 它还提供了启动和停止组成作业的任务的方法。

  cgroup freezer 对于检查运行中的任务组也很有用。 cgroup freezer 通过尝试将cgroup中的任务强制为静止状态,从而允许检查点代码获得任务的一致映像。 一旦任务处于静止状态,另一个任务就可以遍历 /proc 或调用内核接口来收集有关静止任务的信息。 如果出现可恢复的错误,则可以在以后重新启动检查点任务。通过将收集的信息复制到另一个节点并在那里重新启动任务,这也允许检查点任务在集群中的节点之间迁移。

  SIGSTOP 和 SIGCONT 的序列并不总是足以停止和恢复用户空间中的任务。 从我们希望冻结的任务中可以观察到这两种信号。 虽然SIGSTOP不能被捕获,阻止或忽略,但可以通过等待或跟踪父任务来看到它。 SIGCONT更不合适,因为它可能被任务捕获。 试图使用 SIGSTOP 和 SIGCONT 来停止和恢复任务,可能会破坏旨在监视 SIGSTOP 和 SIGCONT 的所有程序。我们可以使用嵌套的bash shell演示此问题:

$ echo $$ 
16644 
$ bash 
$ echo $$ 
16690 
 
# 从另一个无关的bash shell中: 
$ kill -SIGSTOP 16690 
$ kill -SIGCONT 16690

<此时16690退出并导致16644也退出>

发生这种情况是因为bash可以观察到这两种信号并选择对它们的响应方式。

捕获并响应这些信号的程序的另一个示例是gdb。 实际上,任何设计为使用ptrace的程序都可能会遇到这种停止和恢复任务的方法。

相反,cgroup freezer使用内核冻结器代码来防止冻结/解冻循环被要冻结的任务可见。 这使上面的bash示例和gdb可以按预期运行。

cgroup freezer是分层的。 冻结cgroup会冻结属于该cgroup所有的任务以及其后代cgroup的所有任务。 每个cgroup都有其自己的状态(self-state)和从父级继承的状态(parent-state)。 如果两个状态均为 THAWED,则 cgroup 为 THAWED。

以下是由cgroup freezer创建的cgroupfs文件:

* freezer.state: 可读可写. 
 
  读取时,返回cgroup的有效状态-“THAWED”,“FREEZING” 或 “FROZEN”。 这是自身状态和父状态的组合。 如果有任何任务处于freezing状态,
则cgroup处于freezing状态(FREEZING或FROZEN)。   当属于cgroup的所有任务及其子代的所有任务都冻结时,freezeing cgroup转换为FROZEN状态。 请注意,在将新任务添加到cgroup或其后代cgroup之一后,
cgroup将从“FROZEN”状态恢复为“FREEZING”状态,直到这个新任务被冻结。   当写时,设置cgroup的self
-state。 允许使用两个值-“FROZEN”和“THAWED”。 如果写入了FROZEN,则cgroup(如果尚未冻结)连同其所有后代cgroup一起
进入 FREEZING 状态。   如果写入 THAWED,则cgroup的self
-state将变更为 THAWED。 请注意,如果父状态仍处于冻结状态,则有效状态可能不会更改为THAWED。 如果cgroup的有
效状态变为 THAWED,则由于cgroup而冻结的所有后代也将退出冻结状态。
* freezer.self_freezing:只读。   显示self-state。 如果自身状态为 THAWED,则为0;否则为1。 如果最后一次写入 freezer.state 为“FROZEN”,则此值为1。 * freezer.parent_freezing:只读。   显示parent-state。 如果没有冻结cgroup的任何祖先,则为0;否则为1。

root cgroup是不可被冻结的,因此以上接口文件不存在。

用法示例:

# mkdir /sys/fs/cgroup/freezer 
# mount -t cgroup -ofreezer freezer /sys/fs/cgroup/freezer 
# mkdir /sys/fs/cgroup/freezer/0 
# echo $some_pid > /sys/fs/cgroup/freezer/0/tasks

获取freezer子系统的状态:

# cat /sys/fs/cgroup/freezer/0/freezer.state 
THAWED

冻结容器中的所有任务:

# echo FROZEN > /sys/fs/cgroup/freezer/0/freezer.state 
# cat /sys/fs/cgroup/freezer/0/freezer.state 
FREEZING 
# cat /sys/fs/cgroup/freezer/0/freezer.state 
FROZEN

解冻容器中的所有任务:

# echo THAWED > /sys/fs/cgroup/freezer/0/freezer.state 
# cat /sys/fs/cgroup/freezer/0/freezer.state 
THAWED

这是一种基本机制,在简单的情况下,应该针对用户空间任务执行正确的操作。

补充试验:

1. 冻结BASH

/dev/freezer/f_test $ echo $$ > tasks 
/dev/freezer/f_test $ echo FROZEN > freezer.state //此时BASH被冻结,adb终端不响应了。

2. 冻结system_server

/dev/freezer/f_test $ ps -A | grep system_server 
system         1174    783 11609132 467092 __refrigerator     0 D system_server 
/dev/freezer/f_test $ echo 1174 > tasks 
/dev/freezer/f_test $ echo FROZEN > freezer.state //此时亮屏只有壁纸,没有其它任何响应了 
/dev/freezer/f_test $ cat freezer.state //显示system_server进程被冻结了 
FROZEN 
/dev/freezer/f_test $ echo THAWED > freezer.state //解冻system_server进程,此时亮屏系统又有响应了

3. 使用 cgroup.procs 冻结一组任务

/dev/freezer/f_test # getprop xxxx  //确保影响实验的方案是关闭的 
false 
/dev/freezer/f_test # ps -A | grep baidu //事先打开百度浏览器 
u0_a232        9191    834 2473416 360176 do_epoll_wait       0 S com.baidu.searchbox.lite 
u0_a232        9221    834 2003344 119508 do_epoll_wait       0 S com.baidu.searchbox.lite:titanSandbox 
u0_a232        9477    834 2019592 125720 do_epoll_wait       0 S com.baidu.searchbox.lite:bdservice_v1 
u0_a232        9596    834 2103364 165492 do_epoll_wait       0 S com.baidu.searchbox.lite:media 
u0_a232        9691    834 2091780 168116 0                   0 R com.baidu.swan 
/dev/freezer/f_test # echo 9191 > cgroup.procs //将一个任务的PID写到cgroup.procs,将使此线程组中所有任务都移动到线程组中 
/dev/freezer/f_test # cat tasks 
9191 
9201 
... 
9920 
10012 
/dev/freezer/f_test # echo FROZEN > freezer.state //此时百度完全不响应了 
/dev/freezer/f_test # echo THAWED > freezer.state //此时百度恢复正常

本文参考链接:https://www.cnblogs.com/hellokitty2/p/14249661.html