lowmemorykiller&eventfd&cgroup

eventfd

eventfd包含一个由内核维护的64位无符号整型计数器,创建eventfd时会返回一个文件描述符,进程可以通过对这个文件描述符进行read/write来读取/改变计数器的值

用途

  • 线程或者父子进程间通信,是一种事件通知方式
  • 内核通过eventfd也可以向用户空间进程发消息,cgroup就是通过这种方式通知的

当write 的时候计数器会累加

#include <sys/eventfd.h>
//initval:初始值
//EFD_CLOEXEC : close-on-exec 
//EFD_NONBLOCK : non block
//EFD_SEMAPHORE : 信号量 ,读操作只是减1,  如果不是信号量的话,则读出count的值,计数器清0
int eventfd(unsigned int initval, int flags); 

cgroup

用来限制内核内存就是限制当前cgroup所能使用的内核资源

需要kernel的支持
CONFIG_MEMCG=y
CONFIG_MEMCG_KMEM=y

#define MEMCG_SYSFS_PATH "/dev/memcg/"
#define MEMPRESSURE_WATCH_LEVEL "medium"

   mpfd = open(MEMCG_SYSFS_PATH "memory.pressure_level", O_RDONLY);
    if (mpfd < 0) {
        ALOGI("No kernel memory.pressure_level support (errno=%d)", errno);
        goto err_open_mpfd;
    }

    evctlfd = open(MEMCG_SYSFS_PATH "cgroup.event_control", O_WRONLY);
    if (evctlfd < 0) {
        ALOGI("No kernel memory cgroup event control (errno=%d)", errno);
        goto err_open_evctlfd;
    }

    evfd = eventfd(0, EFD_NONBLOCK);
    if (evfd < 0) {
        ALOGE("eventfd failed for level %s; errno=%d", levelstr, errno);
        goto err_eventfd;
    }
	//写入这种格式,会读到内核OOM事件
    ret = snprintf(buf, sizeof(buf), "%d %d %s", evfd, mpfd, levelstr);
    if (ret >= (ssize_t)sizeof(buf)) {
        ALOGE("cgroup.event_control line overflow for level %s", levelstr);
        goto err;
    }

    ret = write(evctlfd, buf, strlen(buf) + 1);

lowmemorykiller
  • 如果use_inkernel_interface=1
    则并不使用cgroup机制,是低版本内核中处理lowmemorykill
  • 使用cgroup机制,在用户态处理lowmemorykill。

内核处理
lowmem_scan
当触发lmkd,则先杀oom_score_adj最大的进程, 当oom_adj相等时,则选择rss最大的进程。

static struct shrinker lowmem_shrinker = {
    .scan_objects = lowmem_scan,
    .count_objects = lowmem_count,
    .seeks = DEFAULT_SEEKS * 16
};

static int __init lowmem_init(void) {
    register_shrinker(&lowmem_shrinker);
    return 0;
}

static void __exit lowmem_exit(void) {
    unregister_shrinker(&lowmem_shrinker);
}
static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
{
	...
		//发送singal kill -9
        send_sig(SIGKILL, selected, 0);
    ...
}
module_init(lowmem_init);
module_exit(lowmem_exit);

和用户态的接口

/sys/module/lowmemorykiller/parameters/minfree
/sys/module/lowmemorykiller/parameters/adj   //adj就是oom_score_adj: 取值范围[-1000, 1000]

//oom_adj:代表进程的优先级, 数值越大,优先级越低,越容易被杀. 取值范围[-16, 15]

#cat /sys/module/lowmemorykiller/parameters/minfree     
18432,23040,27648,32256,36864,46080
#cat /sys/module/lowmemorykiller/parameters/adj       
0,58,117,176,529,1000

#cat /proc/138/oom_adj                                
-17
#cat /proc/138/oom_score                                
0

当系统可用内存低于36864个pages时,则会杀掉oom_score_adj>=529的进程
当系统可用内存低于32256个pages时,则会杀掉oom_score_adj>=176的进程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值