注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

osdba的博客

敢于担当,拥抱变化,锐意进取,永不止步

 
 
 

日志

 
 

cgroup通过eventfd提供内存使用超限通知机制  

2012-07-13 10:18:01|  分类: linux |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
发信人: wxc200 (伊泽), 信区: KernelTech
发信站: 水木社区 (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) 按照如下格式
 <event_fd> <fd of(2)> <args> 
写入到cgroup提供的对event事件的支持属性文件
cgroup.event_control

当内存使用超限,会通过eventfd_signal通知上层。

2.内存oom通知
想监听哪些进程被oom杀死吗? 现在可以了。

类似于前面提到的内存属性文件,OOM在cgroup里通过memory.oom_control提供控制接口。对这个文件进行eventfd操作,memory subsystem会提供会oom杀死进程的事件通知。
操作方式:
<event_fd> <fd of memory.oom_control> ==> cgroup.event_control

当OOM发生时,应用程序会得到通知。


这里有片代码,实现了对cgroup上述属性文件的支持。

/*
 * cgroup_event_listener.c - Simple listener of cgroup events
 *
 * Copyright (C) Kirill A. Shutemov <kirill@shutemov.name>
 */

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <sys/eventfd.h>

#define USAGE_STR "Usage: cgroup_event_listener <path-to-control-file> <args>\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分析:
   http://www.kernel.org/doc/man-pages/online/pages/man2/eventfd.2.html
4) pipe分析:
   http://www.kernel.org/doc/man-pages/online/pages/man2/pipe.2.html
  评论这张
 
阅读(485)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017