ems/ems_c/kernel/kit_core.c

223 lines
6.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************
* @copyright 1997-2050, . POWER SUPPLY CO., LTD.
* @file kit_core.c
* @brief xx功能
* @author Gary
* @date 2024-09-21
* @remark
*****************************************************************************/
#include <errno.h>
#include "kit_core.h"
/*****************************************************************************
* @brief 通过管道执行shell命令 (使用 system)
* @param[in] cmdshell命令
* @param[in] buffer读取执行结果
* @param[in] buffer_size读取执行结果长度
* @return 1-执行错误 0-执行成功
*****************************************************************************/
int kit_popen_exec(const char *cmd, char* buffer, size_t buffer_size)
{
#if IF_RUNIN_VM == RUNIN_VM // 虚拟机环境,返回默认值
return 0;
#endif
FILE *fp = popen(cmd, "r");
if (fp == NULL)
{
KITLOG(LOG_KIT_EN, ERROR_EN, "popen failed");
return 1;
}
// 读取执行结果
size_t bytes_read = fread(buffer, 1, buffer_size - 1, fp); // 最多只读取buffer_size比特数据
if (ferror(fp))
{
KITLOG(LOG_KIT_EN, ERROR_EN, "文件读取失败: %s\n", strerror(errno));
pclose(fp);
return 1;
}
buffer[bytes_read] = '\0'; // 字符串要以NULL结束
int status = pclose(fp);
if (status == -1)
{
KITLOG(LOG_KIT_EN, ERROR_EN, "pclose failed");
return 1;
}
else if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
{
KITLOG(LOG_KIT_EN, ERROR_EN, "CMD命令 '%s' 执行失败,失败的编号: %d\n", cmd, WEXITSTATUS(status));
return 1;
}
return 0;
}
/*****************************************************************************
* @brief 获取网络连接状态
* @param[in] cmdshell命令
* @return 1-网络不可连接 0-网络连接成功
*****************************************************************************/
int kit_get_net_status(void)
{
FILE *fp = popen("ping -c 1 -W 1 www.baidu.com > /dev/null 2>&1", "r");
if (fp == NULL)
{
perror("popen failed");
return 1; // 如果popen失败认为网络不可用
}
// 等待命令执行完毕,获取返回状态
int status = pclose(fp);
// WEXITSTATUS获取子进程返回的状态码ping成功返回0
if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
{
return 0; // 网络可用
}
else
{
return 1; // 网络不可用
}
}
/*****************************************************************************
* @brief 获取EMS的SN号
* @param[in] serial返回SN号
* @return 1-执行错误 0-执行成功
*****************************************************************************/
int kit_get_ems_sn(char serial[128])
{
char buffer[3000]; // 接收执行返回值
char buffer_copy[3000]; // 用于 strtok 的副本
char *line = NULL;
char *serialStart = NULL;
// 使用 kit_popen_exec 执行"cat /proc/cpuinfo"
if (kit_popen_exec("cat /proc/cpuinfo", buffer, sizeof(buffer)) != 0)
{
KITLOG(LOG_DRIVER_EN, ERROR_EN, "cat /proc/cpuinfo 命令执行失败\n");
return 1; // 返回错误
}
strcpy(buffer_copy, buffer); // 复制 buffer 到 buffer_copy
// 使用 strtok 按行分割 buffer_copy
line = strtok(buffer_copy, "\n");
while (line != NULL)
{
// 查找 "Serial" 字符串
if ((serialStart = strstr(line, "Serial")) != NULL)
{
// 提取序列号
serialStart += strlen("Serial\t\t: "); // 跳过 "Serial : "
char *endOfSerial = strchr(serialStart, '\n'); // 查找换行符
if (endOfSerial != NULL)
{
*endOfSerial = '\0'; // 将换行符替换为字符串终止符
}
strncpy(serial, serialStart, 127); // 复制序列号到 serial限制长度防止溢出
serial[127] = '\0'; // 添加字符串终止符
return 0; // 返回成功
}
line = strtok(NULL, "\n");
}
KITLOG(LOG_DRIVER_EN, ERROR_EN, "未找到序列号\n");
return 1; // 返回错误
}
// 获取系统 CPU 时间
void getSysCpuTime(cpu_time_t *time)
{
FILE *file = fopen("/proc/stat", "r");
if (file == NULL)
{
perror("Error opening /proc/stat");
exit(EXIT_FAILURE);
}
fscanf(file, "cpu %lu %lu %lu %lu %lu %lu %lu %lu",
&time->user, &time->nice, &time->system, &time->idle,
&time->iowait, &time->irq, &time->softirq, &time->steal);
fclose(file);
}
// 获取指定进程的 CPU 时间
void getProCpuTime(cpu_time_t *time, pid_t pid)
{
char filename[32];
sprintf(filename, "/proc/%d/stat", pid);
FILE *file = fopen(filename, "r");
if (file == NULL)
{
perror("Error opening process stat file");
exit(EXIT_FAILURE);
}
uint64_t utime, stime;
fscanf(file, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu %lu", &utime, &stime);
time->user = utime;
time->system = stime;
fclose(file);
}
// 获取内存信息的函数
void getMemInfo(memory_info_t *info)
{
FILE *file = fopen("/proc/meminfo", "r"); // 打开 /proc/meminfo 文件
if (file == NULL)
{
perror("Error opening /proc/meminfo"); // 如果打开失败,打印错误信息并退出
return;
}
// 从文件中读取内存信息,包括总内存、空闲内存、可用内存、缓冲区内存和缓存内存
fscanf(file, "MemTotal: %lu kB\nMemFree: %lu kB\nMemAvailable: %lu kB\nBuffers: %lu kB\nCached: %lu kB",
&info->total, &info->free, &info->available, &info->buffers, &info->cached);
fclose(file); // 关闭文件
}
// 函数用于提取指定关键字后的整数值
int extractValue(const char *line, const char *keyword)
{
char *pos = strstr(line, keyword);
if (pos == NULL)
{
return -1;
}
pos += strlen(keyword);
int value;
sscanf(pos, "%d", &value);
return value;
}
// 计算当前进程内存占用
double calculateProcMemUsage(memory_info_t info, pid_t pid)
{
char filename[32];
sprintf(filename, "/proc/%d/status", pid);
FILE *file = fopen(filename, "r");
if (file == NULL)
{
// perror("Error opening process status file");
return 0.0;
}
char line[256];
int rss = -1;
while (fgets(line, sizeof(line), file))
{
if (rss == -1 && strstr(line, "VmRSS") != NULL)
{
rss = extractValue(line, "VmRSS:");
}
}
fclose(file);
if (rss != -1)
{
// printf("Current process resident memory size: %d kB\n", rss);
return (double)rss / info.total * 100.0;
}
else
{
// printf("Failed to get process memory usage.\n");
return 0.0;
}
}