背景
memory cgroup中没有任务,但memory.stat中的cache统计项显示有值,经排查是共享内存没有释放,故进行问题复现和原理追究。
问题复现
问题复现的总体思路也很简单,就是创建两个进程,这个两个进程使用共享内存进行通信,如何将一个进程加入到一个memoy cgroup中,查看内存统计值。
先查看当前系统的共享内存使用情况。如下图所示,当前系统shared的值为25M,当前系统没有利用共享内存进行通信的进程。
生成大小为20M的共享内存,代码如下。
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
//生成一个key
key_t key = ftok("./", 88);
//创建共享内存,返回一个id
//数字 4 、2 和 1表示读、写、执行权限
//用户、所属组、其他组都有读写权限
int shmid = shmget(key, 20*1024*1024, IPC_CREAT|0666); // IPC_CREAT: Create entry if key does not exist
printf("共享内存的shmid is %d \n", shmid);
if (shmid == -1) {
perror("shmget failed");
//exit(0) 表示程序正常退出,exit⑴/exit(-1)表示程序异常退出。
exit(1);
}
//映射共享内存,得到虚拟地址
//shmaddr:指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置
//shmflg: SHM_RDONLY:为只读模式,其他为读写模式
void *p = shmat(shmid, NULL, 0);
if (p == (void *)-1) {
perror("shmat failed");
exit(2);
}
//写共享内存
int *pp = p;
int i;
for(i=0;i<20*1024*1024/4;i++){
*(pp + i) = i;
}
printf("写入共享内存成功,点击回车解除内存映射\n");
getchar();
//解除映射
if (shmdt(p) == -1) {
printf("shmdt failed");
exit(3);
}
printf("解除映射成功,点击回车销毁共享内存\n");
getchar();
//IPC_RMID:删除这片共享内存
if (shmctl(shmid, IPC_RMID, NULL)) {
perror("shmctl failed");
exit(4);
}
return 0;
}
读取共享内存中的值,代码如下:
#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdlib.h>
int main() {
//生成key
key_t key = ftok("./", 88);
//获取共享内存,返回id
//0:只获取共享内存时指定为0
//shmflg0:取共享内存标识符,若不存在则函数会报错
int shmid = shmget(key, 0, 0);
if (shmid == -1) {
perror("shmget failed");
exit(1);
}
//映射共享内存,得到虚拟地址
void *p = shmat(shmid, 0, 0);
if (p == (void *)-1) {
perror("shmat failed");
exit(2);
}
//读取共享内存
int data1 = *(int *)p;
int data2 = *((int *)p + 1);
printf("共享内存第1000个的数为 %d", *((int *)p + 999));
//printf("从共享内存中读取了,%x 和 %x\n", data1, data2);
printf("点击回车解除共享内存映射\n");
getchar();
//解除映射
if(shmdt(p) == -1) {
perror("shmdt failed");
exit(3);
}
return 0;
}
从上图可以看到,有两个进程正在使用共享内存进行通信,下面将读进程利用memory cgroup进行内存限制。
查看内存统计信息,发现内存使用为0,复现失败!!
发现没有按预期出现问题,顿时不知所措,查阅相关资料,了解了共享内存有多种实现方式,故试一试其它共享内存的方式。