179 lines
4.9 KiB
C
179 lines
4.9 KiB
C
//
|
|
// Created by xajhu on 2021/7/6 0006.
|
|
//
|
|
#include <stdlib.h>
|
|
#include <uv.h>
|
|
#include <string.h>
|
|
#include <sds/sds.h>
|
|
|
|
#include "hardware.h"
|
|
#include "user_errno.h"
|
|
#include "uthash/uthash.h"
|
|
#include "misc.h"
|
|
#include "config.h"
|
|
|
|
#define CMD_MEMORY_INFO ("cat /proc/meminfo | awk \'{print $1\"|\"$2\"|\"$3}\'")
|
|
|
|
#define M_SIZE (1024 * 1024)
|
|
|
|
#define KEY_NAME (32)
|
|
#define KEY_VALUE (32)
|
|
#define VALUE_UNIT (8)
|
|
|
|
typedef struct {
|
|
char itemName[KEY_NAME];
|
|
char itemValue[KEY_VALUE];
|
|
char valUnit[VALUE_UNIT];
|
|
unsigned long timestamp;
|
|
|
|
UT_hash_handle hh;
|
|
} KERNEL_MEM_INFO, *PKERNEL_MEM_INFO;
|
|
|
|
static uv_rwlock_t g_uvLock;
|
|
static PKERNEL_MEM_INFO g_pMemInfo = NULL;
|
|
static const char *g_memKeyName[] = {"MemTotal", "MemFree", "MemAvailable", "Buffers", "Cached"};
|
|
|
|
unsigned int get_sys_free_memory() {
|
|
return uv_get_free_memory() / M_SIZE;
|
|
}
|
|
|
|
unsigned int get_sys_total_memory() {
|
|
return uv_get_total_memory() / M_SIZE;
|
|
}
|
|
|
|
static int memory_info_refresh() {
|
|
int errCode = ERR_SUCCESS;
|
|
FILE *fp;
|
|
char buf[MAX_PATH * 2];
|
|
|
|
fp = popen(CMD_MEMORY_INFO, "r");
|
|
|
|
if (fp == NULL) {
|
|
return -ERR_OPEN_FILE;
|
|
}
|
|
|
|
while (fgets(buf, 1024, fp) != NULL) {
|
|
int nItems;
|
|
sds tmpStr = sdsnew(buf);
|
|
sds *pToken = sdssplitlen(tmpStr, (int)sdslen(tmpStr), "|", 1, &nItems);
|
|
|
|
if (nItems == 3) {
|
|
PKERNEL_MEM_INFO pTmp = NULL;
|
|
|
|
HASH_FIND_STR(g_pMemInfo, pToken[0], pTmp);
|
|
|
|
if (pTmp) {
|
|
uv_rwlock_wrlock(&g_uvLock);
|
|
strcpy(pTmp->itemName, sdstrim(pToken[0], ": \n"));
|
|
strcpy(pTmp->itemValue, sdstrim(pToken[1], " \n"));
|
|
strcpy(pTmp->valUnit, sdstrim(pToken[2], " \n"));
|
|
pTmp->timestamp = time(NULL);
|
|
uv_rwlock_wrunlock(&g_uvLock);
|
|
} else {
|
|
pTmp = (PKERNEL_MEM_INFO)malloc(sizeof(KERNEL_MEM_INFO));
|
|
|
|
if (pTmp) {
|
|
uv_rwlock_wrlock(&g_uvLock);
|
|
strcpy(pTmp->itemName, sdstrim(pToken[0], ": \n"));
|
|
strcpy(pTmp->itemValue, sdstrim(pToken[1], " \n"));
|
|
strcpy(pTmp->valUnit, sdstrim(pToken[2], " \n"));
|
|
pTmp->timestamp = time(NULL);
|
|
HASH_ADD_STR(g_pMemInfo, itemName, pTmp);
|
|
uv_rwlock_wrunlock(&g_uvLock);
|
|
} else {
|
|
errCode = -ERR_MALLOC_MEMORY;
|
|
}
|
|
}
|
|
}
|
|
|
|
sdsfreesplitres(pToken, nItems);
|
|
sdsfree(tmpStr);
|
|
}
|
|
|
|
return errCode;
|
|
}
|
|
|
|
_Noreturn void memRefreshCb(void *UNUSED(pArg)) {
|
|
do {
|
|
unsigned int period = cfg_get_mem_refresh_period();
|
|
|
|
if (cfg_get_watch_memory()) {
|
|
memory_info_refresh();
|
|
}
|
|
|
|
if (period < REFRESH_MAX_PERIOD && period >= 1) {
|
|
uv_sleep(1000 * period);
|
|
} else {
|
|
uv_sleep(1000);
|
|
}
|
|
} while (TRUE);
|
|
}
|
|
|
|
int memory_watch_init() {
|
|
static uv_thread_t uvThread;
|
|
|
|
uv_rwlock_init(&g_uvLock);
|
|
|
|
if (memory_info_refresh() != ERR_SUCCESS) {
|
|
return -ERR_SYS_DISK_GET_INFO;
|
|
}
|
|
|
|
uv_thread_create(&uvThread, memRefreshCb, NULL);
|
|
|
|
return ERR_SUCCESS;
|
|
}
|
|
|
|
#define MEM_VALUE_SET(dst, src) \
|
|
do { \
|
|
if ((src) == NULL) \
|
|
continue; \
|
|
if ((src)->valUnit && strlen((src)->valUnit) > 0) { \
|
|
sprintf(dst, "%s %s", (src)->itemValue, (src)->valUnit); \
|
|
} else { \
|
|
sprintf(dst, "%s", (src)->itemValue); \
|
|
} \
|
|
} while (0)
|
|
|
|
int get_memory_info(PMEMORY_INFO pInfo) {
|
|
int i, n = ARRAY_SIZE(g_memKeyName);
|
|
if (pInfo == NULL) {
|
|
return -ERR_INPUT_PARAMS;
|
|
}
|
|
|
|
uv_rwlock_rdlock(&g_uvLock);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
PKERNEL_MEM_INFO pTmp = NULL;
|
|
|
|
HASH_FIND_STR(g_pMemInfo, g_memKeyName[i], pTmp);
|
|
|
|
if (pTmp) {
|
|
switch (i) {
|
|
case 0:
|
|
MEM_VALUE_SET(pInfo->totalMemSize, pTmp);
|
|
break;
|
|
case 1:
|
|
MEM_VALUE_SET(pInfo->freeMemSize, pTmp);
|
|
break;
|
|
case 2:
|
|
MEM_VALUE_SET(pInfo->availMemSize, pTmp);
|
|
break;
|
|
case 3:
|
|
MEM_VALUE_SET(pInfo->bufferMemSize, pTmp);
|
|
break;
|
|
case 4:
|
|
MEM_VALUE_SET(pInfo->cachedMemSize, pTmp);
|
|
break;
|
|
default:
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
uv_rwlock_rdunlock(&g_uvLock);
|
|
|
|
pInfo->timestamp = time(NULL);
|
|
|
|
return ERR_SUCCESS;
|
|
}
|