/***************************************************************************** * @copyright 1997-2050, . POWER SUPPLY CO., LTD. * @file kit_core.c * @brief xx功能 * @author Gary * @date 2024-09-21 * @remark *****************************************************************************/ #include #include "kit_core.h" /***************************************************************************** * @brief 通过管道执行shell命令 (使用 system) * @param[in] cmd:shell命令 * @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] cmd:shell命令 * @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; } }