发信人: wxc200 (伊泽), 信区: KernelTech
标 题: cgroup通过eventfd提供内存使用超限通知机制
发信站: 水木社区 (Sun Jan 16 23:20:23 2011), 转信
1.内存threshold阀值限制
内存资源控制subsystem提供cgroup通知机制,用户态程序可以向cgroup注册对内存资源的阀值监控,当进程使用内存超限时,会通过eventfd通知用户态的监听进程。
用户mount内存的subsystem时,在cgroup目录下有memory.usage_in_bytes 或者memory_memsw.usage_in_bytes属性文件,那么对这两种资源监控需要如下几步:
1) 用系统调用eventfd(2)创建eventfd文件。
2)打开上述属性文件
3) 按照如下格式
写入到cgroup提供的对event事件的支持属性文件
cgroup.event_control
当内存使用超限,会通过eventfd_signal通知上层。
2.内存oom通知
想监听哪些进程被oom杀死吗? 现在可以了。
类似于前面提到的内存属性文件,OOM在cgroup里通过memory.oom_control提供控制接口。对这个文件进行eventfd操作,memory subsystem会提供会oom杀死进程的事件通知。
操作方式:
==> cgroup.event_control
当OOM发生时,应用程序会得到通知。
这里有片代码,实现了对cgroup上述属性文件的支持。
/*
* cgroup_event_listener.c - Simple listener of cgroup events
*
* Copyright (C) Kirill A. Shutemov
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define USAGE_STR "Usage: cgroup_event_listener \n"
int main(int argc, char **argv)
{
int efd = -1;
int cfd = -1;
int event_control = -1;
char event_control_path[PATH_MAX];
char line[LINE_MAX];
int ret;
if (argc != 3) {
fputs(USAGE_STR, stderr);
return 1;
}
cfd = open(argv[1], O_RDONLY); //要操作的subsystem属性文件
if (cfd == -1) {
fprintf(stderr, "Cannot open %s: %s\n", argv[1],
strerror(errno));
goto out;
}
ret = snprintf(event_control_path, PATH_MAX, "%s/cgroup.event_control", //将参数写到这个配置文件里。内核对此文件的支持很清晰,后面会分析到。
dirname(argv[1]));
if (ret >= PATH_MAX) {
fputs("Path to cgroup.event_control is too long\n", stderr);
goto out;
}
event_control = open(event_control_path, O_WRONLY);//打开cgroup event.control配置文件
if (event_control == -1) {
fprintf(stderr, "Cannot open %s: %s\n", event_control_path,
strerror(errno));
goto out;
}
efd = eventfd(0, 0); //创建eventfd
if (efd == -1) {
perror("eventfd() failed");
goto out;
}
ret = snprintf(line, LINE_MAX, "%d %d %s", efd, cfd, argv[2]); //合成要写入的字符串
if (ret >= LINE_MAX) {
fputs("Arguments string is too long\n", stderr);
goto out;
}
ret = write(event_control, line, strlen(line) + 1);
if (ret == -1) {
perror("Cannot write to cgroup.event_control");
goto out;
}
//完成写入,守候通知吧。
while (1) {
uint64_t result;
ret = read(efd, &result, sizeof(result)); //读取event count数值
if (ret == -1) {
if (errno == EINTR)
continue;
perror("Cannot read from eventfd");
break;
}
assert(ret == sizeof(result));
ret = access(event_control_path, W_OK);
if ((ret == -1) && (errno == ENOENT)) {
puts("The cgroup seems to have removed.");
ret = 0;
break;
}
if (ret == -1) {
perror("cgroup.event_control "
"is not accessable any more");
break;
}
printf("%s %s: crossed\n", argv[1], argv[2]);
}
out:
if (efd >= 0)
close(efd);
if (event_control >= 0)
close(event_control);
if (cfd >= 0)
close(cfd);
return (ret != 0);
}
Coming soon:
1) 分析内核cgroup和相应subsystem(memory)对eventfd的支持
2) eventfd 的实现
3) eventfd/pipe等机制的比较。
参考文献:
0) cgroup.c eventfd.c memcontrol.c anon_inodes.c
1) Documentation/cgroup/memory.txt+cgroup.txt
2) cgroup_event_listener.c
3) eventfd分析:
4) pipe分析:
阅读(2113) | 评论(0) | 转发(0) |