times 函数详解
1. 函数介绍
times
是POSIX标准函数,用于获取进程及其子进程的CPU时间统计信息。它返回自系统启动以来进程在用户态和内核态消耗的CPU时间,以及所有已终止子进程的CPU时间统计。这对于性能分析、资源监控和系统管理非常有用。
2. 函数原型
#include <sys/times.h>
clock_t times(struct tms *buf);
3. 功能
times
函数获取当前进程的CPU时间使用情况,包括用户态CPU时间、系统态CPU时间,以及所有已终止子进程的相应时间。这些信息对于进程性能分析和资源管理至关重要。
4. 参数
*struct tms buf : 指向tms结构体的指针,用于存储时间统计信息
5. 返回值
成功 : 返回自系统启动以来的滴答数(ticks)
失败 : 返回(clock_t)-1,并设置errno
6. 相似函数,或关联函数
clock : 获取进程CPU时间
getrusage : 获取资源使用情况
time/clock_gettime : 获取系统时间
wait/waitpid : 等待子进程并获取其资源使用情况
7. 示例代码
示例1:基础times使用
#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
/**
* 显示CPU时间统计
*/
void show_cpu_times(const struct tms *tms_buf, clock_t ticks) {
long clk_tck = sysconf(_SC_CLK_TCK); // 获取每秒滴答数
printf("CPU时间统计:\n");
printf(" 用户态时间: %jd 滴答 (%.3f 秒)\n",
(intmax_t)tms_buf->tms_utime,
(double)tms_buf->tms_utime / clk_tck);
printf(" 系统态时间: %jd 滴答 (%.3f 秒)\n",
(intmax_t)tms_buf->tms_stime,
(double)tms_buf->tms_stime / clk_tck);
printf(" 子进程用户态时间: %jd 滴答 (%.3f 秒)\n",
(intmax_t)tms_buf->tms_cutime,
(double)tms_buf->tms_cutime / clk_tck);
printf(" 子进程系统态时间: %jd 滴答 (%.3f 秒)\n",
(intmax_t)tms_buf->tms_cstime,
(double)tms_buf->tms_cstime / clk_tck);
printf(" 总滴答数: %jd\n", (intmax_t)ticks);
printf(" 系统滴答率: %ld 滴答/秒\n", clk_tck);
}
/**
* 演示基础times使用方法
*/
int demo_times_basic() {
struct tms tms_start, tms_end;
clock_t start_ticks, end_ticks;
long clk_tck;
printf("=== 基础times使用示例 ===\n");
// 获取系统滴答率
clk_tck = sysconf(_SC_CLK_TCK);
if (clk_tck == -1) {
perror("获取系统滴答率失败");
return -1;
}
printf("系统滴答率: %ld 滴答/秒\n", clk_tck);
// 获取初始时间统计
start_ticks = times(&tms_start);
if (start_ticks == (clock_t)-1) {
perror("获取初始时间统计失败");
return -1;
}
printf("\n1. 初始时间统计:\n");
show_cpu_times(&tms_start, start_ticks);
// 执行一些CPU密集型操作
printf("\n2. 执行CPU密集型操作...\n");
volatile long sum = 0;
for (long i = 0; i < 100000000; i++) {
sum += i * i;
if (i % 20000000 == 0) {
printf(" 进度: %ld%%\n", i / 1000000);
}
}
printf(" 计算结果: %ld\n", sum);
// 获取结束时间统计
end_ticks = times(&tms_end);
if (end_ticks == (clock_t)-1) {
perror("获取结束时间统计失败");
return -1;
}
printf("\n3. 结束时间统计:\n");
show_cpu_times(&tms_end, end_ticks);
// 计算时间差
printf("\n4. 时间差统计:\n");
clock_t ticks_diff = end_ticks - start_ticks;
clock_t utime_diff = tms_end.tms_utime - tms_start.tms_utime;
clock_t stime_diff = tms_end.tms_stime - tms_start.tms_stime;
printf(" 消耗滴答数: %jd\n", (intmax_t)ticks_diff);
printf(" 用户态时间差: %jd 滴答 (%.3f 秒)\n",
(intmax_t)utime_diff, (double)utime_diff / clk_tck);
printf(" 系统态时间差: %jd 滴答 (%.3f 秒)\n",
(intmax_t)stime_diff, (double)stime_diff / clk_tck);
printf(" 总CPU时间: %.3f 秒\n",
(double)(utime_diff + stime_diff) / clk_tck);
// 计算CPU使用率
if (ticks_diff > 0) {
double cpu_utilization = (double)(utime_diff + stime_diff) / ticks_diff * 100;
printf(" CPU使用率: %.2f%%\n", cpu_utilization);
}
return 0;
}
int main() {
return demo_times_basic();
}
示例2:父子进程CPU时间统计
#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
/**
* 子进程工作函数
*/
void child_work(int child_id, int work_duration) {
printf("子进程 %d (PID: %d) 启动\n", child_id, getpid());
struct tms tms_start, tms_current;
clock_t start_ticks, current_ticks;
long clk_tck = sysconf(_SC_CLK_TCK);
start_ticks = times(&tms_start);
// 执行工作
volatile long sum = 0;
time_t start_time = time(NULL);
while (difftime(time(NULL), start_time) < work_duration) {
// CPU密集型工作
for (int i = 0; i < 1000000; i++) {
sum += i;
}
// 定期报告进度
if (difftime(time(NULL), start_time) > 0 &&
fmod(difftime(time(NULL), start_time), 1.0) < 0.1) {
current_ticks = times(&tms_current);
if (current_ticks != (clock_t)-1) {
clock_t utime_diff = tms_current.tms_utime - tms_start.tms_utime;
printf(" 子进程 %d: 用户态时间 %.3f 秒\n",
child_id, (double)utime_diff / clk_tck);
}
}
}
printf("子进程 %d 完成,计算结果: %ld\n", child_id, sum);
exit(child_id);
}
/**
* 演示父子进程CPU时间统计
*/
int demo_parent_child_times() {
struct tms tms_before, tms_after;
clock_t ticks_before, ticks_after;
pid_t children[3];
int child_count = 3;
long clk_tck = sysconf(_SC_CLK_TCK);
printf("=== 父子进程CPU时间统计演示 ===\n");
printf("系统滴答率: %ld 滴答/秒\n", clk_tck);
// 获取父进程初始时间统计
ticks_before = times(&tms_before);
if (ticks_before == (clock_t)-1) {
perror("获取初始时间统计失败");
return -1;
}
printf("\n1. 父进程初始时间统计:\n");
printf(" 父进程用户态时间: %.3f 秒\n",
(double)tms_before.tms_utime / clk_tck);
printf(" 父进程系统态时间: %.3f 秒\n",
(double)tms_before.tms_stime / clk_tck);
printf(" 子进程累计时间: %.3f 秒 (用户态) + %.3f 秒 (系统态)\n",
(double)tms_before.tms_cutime / clk_tck,
(double)tms_before.tms_cstime / clk_tck);
// 创建子进程
printf("\n2. 创建子进程:\n");
for (int i = 0; i < child_count; i++) {
children[i] = fork();
if (children[i] == 0) {
// 子进程
child_work(i + 1, 3 + i); // 不同持续时间
} else if (children[i] > 0) {
printf(" 创建子进程 %d: PID=%d\n", i + 1, children[i]);
} else {
perror("创建子进程失败");
// 清理已创建的子进程
for (int j = 0; j < i; j++) {
kill(children[j], SIGKILL);
}
return -1;
}
}
// 父进程等待子进程完成
printf("\n3. 父进程等待子进程完成:\n");
int completed_children = 0;
while (completed_children < child_count) {
int status;
pid_t finished_pid = wait(&status);
if (finished_pid > 0) {
completed_children++;
printf(" 子进程 %d (PID=%d) 已完成,退出状态: %d\n",
WEXITSTATUS(status), finished_pid, WEXITSTATUS(status));
} else if (finished_pid == -1) {
if (errno != EINTR) {
perror("等待子进程失败");
break;
}
}
}
// 获取父进程结束时间统计
ticks_after = times(&tms_after);
if (ticks_after == (clock_t)-1) {
perror("获取结束时间统计失败");
return -1;
}
printf("\n4. 父进程结束时间统计:\n");
printf(" 父进程用户态时间: %.3f 秒\n",
(double)tms_after.tms_utime / clk_tck);
printf(" 父进程系统态时间: %.3f 秒\n",
(double)tms_after.tms_stime / clk_tck);
printf(" 子进程累计时间: %.3f 秒 (用户态) + %.3f 秒 (系统态)\n",
(double)tms_after.tms_cutime / clk_tck,
(double)tms_after.tms_cstime / clk_tck);
// 计算差异
printf("\n5. 父子进程时间差异分析:\n");
clock_t parent_utime_diff = tms_after.tms_utime - tms_before.tms_utime;
clock_t parent_stime_diff = tms_after.tms_stime - tms_before.tms_stime;
clock_t children_utime_diff = tms_after.tms_cutime - tms_before.tms_cutime;
clock_t children_stime_diff = tms_after.tms_cstime - tms_before.tms_cstime;
printf(" 父进程CPU时间: %.3f 秒 (用户态) + %.3f 秒 (系统态) = %.3f 秒\n",
(double)parent_utime_diff / clk_tck,
(double)parent_stime_diff / clk_tck,
(double)(parent_utime_diff + parent_stime_diff) / clk_tck);
printf(" 子进程CPU时间: %.3f 秒 (用户态) + %.3f 秒 (系统态) = %.3f 秒\n",
(double)children_utime_diff / clk_tck,
(double)children_stime_diff / clk_tck,
(double)(children_utime_diff + children_stime_diff) / clk_tck);
printf(" 总CPU时间: %.3f 秒\n",
(double)(parent_utime_diff + parent_stime_diff +
children_utime_diff + children_stime_diff) / clk_tck);
// 总体统计
clock_t total_ticks = ticks_after - ticks_before;
if (total_ticks > 0) {
double total_cpu_time = (double)(parent_utime_diff + parent_stime_diff +
children_utime_diff + children_stime_diff) / clk_tck;
double wall_clock_time = (double)total_ticks / clk_tck;
double cpu_utilization = total_cpu_time / wall_clock_time * 100;
printf("\n6. 总体性能统计:\n");
printf(" 墙钟时间: %.3f 秒\n", wall_clock_time);
printf(" CPU时间: %.3f 秒\n", total_cpu_time);
printf(" CPU利用率: %.2f%%\n", cpu_utilization);
printf(" 并行效率: %.2f%%\n", cpu_utilization / child_count);
}
return 0;
}
int main() {
return demo_parent_child_times();
}
示例3:性能分析工具
#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <math.h>
/**
* 性能分析结果结构
*/
typedef struct {
clock_t start_ticks;
clock_t end_ticks;
struct tms start_tms;
struct tms end_tms;
double wall_time_seconds;
double cpu_time_seconds;
double user_time_seconds;
double system_time_seconds;
double children_user_time_seconds;
double children_system_time_seconds;
double cpu_utilization_percent;
} performance_analysis_t;
/**
* 初始化性能分析
*/
int init_performance_analysis(performance_analysis_t *analysis) {
analysis->start_ticks = times(&analysis->start_tms);
if (analysis->start_ticks == (clock_t)-1) {
perror("初始化性能分析失败");
return -1;
}
return 0;
}
/**
* 完成性能分析
*/
int finish_performance_analysis(performance_analysis_t *analysis) {
long clk_tck = sysconf(_SC_CLK_TCK);
analysis->end_ticks = times(&analysis->end_tms);
if (analysis->end_ticks == (clock_t)-1) {
perror("完成性能分析失败");
return -1;
}
// 计算各种时间统计
clock_t ticks_diff = analysis->end_ticks - analysis->start_ticks;
clock_t utime_diff = analysis->end_tms.tms_utime - analysis->start_tms.tms_utime;
clock_t stime_diff = analysis->end_tms.tms_stime - analysis->start_tms.tms_stime;
clock_t cutime_diff = analysis->end_tms.tms_cutime - analysis->start_tms.tms_cutime;
clock_t cstime_diff = analysis->end_tms.tms_cstime - analysis->start_tms.tms_cstime;
analysis->wall_time_seconds = (double)ticks_diff / clk_tck;
analysis->user_time_seconds = (double)utime_diff / clk_tck;
analysis->system_time_seconds = (double)stime_diff / clk_tck;
analysis->children_user_time_seconds = (double)cutime_diff / clk_tck;
analysis->children_system_time_seconds = (double)cstime_diff / clk_tck;
analysis->cpu_time_seconds = analysis->user_time_seconds + analysis->system_time_seconds +
analysis->children_user_time_seconds + analysis->children_system_time_seconds;
if (ticks_diff > 0) {
analysis->cpu_utilization_percent = (analysis->cpu_time_seconds /
analysis->wall_time_seconds) * 100;
} else {
analysis->cpu_utilization_percent = 0.0;
}
return 0;
}
/**
* 显示性能分析结果
*/
void show_performance_analysis(const performance_analysis_t *analysis) {
printf("=== 性能分析报告 ===\n");
printf("时间统计:\n");
printf(" 墙钟时间: %.3f 秒\n", analysis->wall_time_seconds);
printf(" 用户态时间: %.3f 秒\n", analysis->user_time_seconds);
printf(" 系统态时间: %.3f 秒\n", analysis->system_time_seconds);
printf(" 子进程用户态时间: %.3f 秒\n", analysis->children_user_time_seconds);
printf(" 子进程系统态时间: %.3f 秒\n", analysis->children_system_time_seconds);
printf(" 总CPU时间: %.3f 秒\n", analysis->cpu_time_seconds);
printf(" CPU利用率: %.2f%%\n", analysis->cpu_utilization_percent);
// 详细分解
printf("\n详细分解:\n");
if (analysis->wall_time_seconds > 0) {
printf(" 用户态占比: %.1f%%\n",
(analysis->user_time_seconds / analysis->wall_time_seconds) * 100);
printf(" 系统态占比: %.1f%%\n",
(analysis->system_time_seconds / analysis->wall_time_seconds) * 100);
printf(" 子进程用户态占比: %.1f%%\n",
(analysis->children_user_time_seconds / analysis->wall_time_seconds) * 100);
printf(" 子进程系统态占比: %.1f%%\n",
(analysis->children_system_time_seconds / analysis->wall_time_seconds) * 100);
}
}
/**
* CPU密集型测试函数
*/
void cpu_intensive_test(const char *test_name, int iterations) {
printf("执行CPU密集型测试: %s (%d 次迭代)\n", test_name, iterations);
volatile double result = 0.0;
for (int i = 0; i < iterations; i++) {
// 执行数学计算
for (int j = 1; j <= 1000; j++) {
result += sin(j * 0.001) * cos(j * 0.001);
}
// 定期显示进度
if (i > 0 && i % (iterations / 10) == 0) {
printf(" %s 进度: %d%%\n", test_name, (i * 100) / iterations);
}
}
printf(" %s 完成,结果: %.6f\n", test_name, result);
}
/**
* I/O密集型测试函数
*/
void io_intensive_test(const char *test_name, int file_count) {
printf("执行I/O密集型测试: %s (%d 个文件)\n", test_name, file_count);
for (int i = 0; i < file_count; i++) {
char filename[64];
snprintf(filename, sizeof(filename), "/tmp/io_test_%s_%d.tmp", test_name, i);
// 创建并写入文件
FILE *fp = fopen(filename, "w");
if (fp) {
for (int j = 0; j < 1000; j++) {
fprintf(fp, "测试数据行 %d.%d\n", i, j);
}
fclose(fp);
}
// 读取文件
fp = fopen(filename, "r");
if (fp) {
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp)) {
// 简单处理读取的数据
volatile int dummy = strlen(buffer);
}
fclose(fp);
}
// 删除临时文件
unlink(filename);
if (i > 0 && i % (file_count / 10) == 0) {
printf(" %s 进度: %d%%\n", test_name, (i * 100) / file_count);
}
}
printf(" %s 完成\n", test_name);
}
/**
* 演示性能分析工具
*/
int demo_performance_analyzer() {
performance_analysis_t analysis;
long clk_tck = sysconf(_SC_CLK_TCK);
printf("=== 性能分析工具演示 ===\n");
printf("系统滴答率: %ld 滴答/秒\n", clk_tck);
// 初始化性能分析
if (init_performance_analysis(&analysis) != 0) {
return -1;
}
printf("\n开始性能测试...\n");
// 测试1: CPU密集型操作
printf("\n1. CPU密集型测试:\n");
cpu_intensive_test("CPU测试1", 5000);
// 测试2: I/O密集型操作
printf("\n2. I/O密集型测试:\n");
io_intensive_test("I/O测试1", 50);
// 测试3: 混合操作
printf("\n3. 混合操作测试:\n");
for (int i = 0; i < 5; i++) {
cpu_intensive_test("混合CPU测试", 1000);
io_intensive_test("混合I/O测试", 10);
}
// 完成性能分析
if (finish_performance_analysis(&analysis) != 0) {
return -1;
}
// 显示分析结果
printf("\n");
show_performance_analysis(&analysis);
// 详细性能建议
printf("\n=== 性能优化建议 ===\n");
if (analysis.cpu_utilization_percent > 80) {
printf("📌 CPU使用率很高 (%.1f%%),可能存在CPU瓶颈\n",
analysis.cpu_utilization_percent);
printf(" 建议:\n");
printf(" - 考虑算法优化\n");
printf(" - 检查是否存在无限循环\n");
printf(" - 考虑并行处理\n");
} else if (analysis.cpu_utilization_percent > 50) {
printf("ℹ CPU使用率中等 (%.1f%%)\n", analysis.cpu_utilization_percent);
printf(" 建议:\n");
printf(" - 监控CPU使用趋势\n");
printf(" - 优化热点代码\n");
} else {
printf("✓ CPU使用率正常 (%.1f%%)\n", analysis.cpu_utilization_percent);
}
// I/O性能分析
double io_ratio = (analysis.children_user_time_seconds +
analysis.children_system_time_seconds) /
analysis.wall_time_seconds;
if (io_ratio > 0.3) {
printf("\n📌 I/O操作占比较高 (%.1f%%)\n", io_ratio * 100);
printf(" 建议:\n");
printf(" - 考虑异步I/O操作\n");
printf(" - 优化文件访问模式\n");
printf(" - 使用缓冲减少I/O次数\n");
}
// 并行效率分析
if (analysis.children_user_time_seconds + analysis.children_system_time_seconds > 0) {
printf("\n📊 子进程性能分析:\n");
printf(" 子进程总CPU时间: %.3f 秒\n",
analysis.children_user_time_seconds + analysis.children_system_time_seconds);
printf(" 平均每个子进程CPU时间: %.3f 秒\n",
(analysis.children_user_time_seconds + analysis.children_system_time_seconds) / 2);
}
return 0;
}
int main() {
return demo_performance_analyzer();
}
示例4:实时CPU监控
#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
/**
* CPU监控数据结构
*/
typedef struct {
time_t timestamp;
clock_t ticks;
struct tms tms_data;
double cpu_usage_percent;
double user_cpu_percent;
double system_cpu_percent;
double children_cpu_percent;
} cpu_monitor_data_t;
/**
* CPU监控器结构
*/
typedef struct {
cpu_monitor_data_t history[100]; // 历史数据
int history_count;
int max_history;
long clk_tck;
volatile int monitoring;
pid_t target_pid; // 监控特定进程(0表示当前进程)
} cpu_monitor_t;
/**
* 初始化CPU监控器
*/
int init_cpu_monitor(cpu_monitor_t *monitor, pid_t target_pid) {
memset(monitor, 0, sizeof(cpu_monitor_t));
monitor->max_history = 100;
monitor->clk_tck = sysconf(_SC_CLK_TCK);
monitor->target_pid = target_pid;
monitor->monitoring = 1;
if (monitor->clk_tck == -1) {
perror("获取系统滴答率失败");
return -1;
}
printf("CPU监控器初始化完成\n");
printf(" 监控目标: %s\n", target_pid ? "特定进程" : "当前进程");
printf(" 系统滴答率: %ld 滴答/秒\n", monitor->clk_tck);
return 0;
}
/**
* 收集CPU使用数据
*/
int collect_cpu_data(cpu_monitor_t *monitor) {
if (monitor->history_count >= monitor->max_history) {
// 循环覆盖旧数据
memmove(&monitor->history[0], &monitor->history[1],
sizeof(cpu_monitor_data_t) * (monitor->max_history - 1));
monitor->history_count = monitor->max_history - 1;
}
cpu_monitor_data_t *current = &monitor->history[monitor->history_count];
current->timestamp = time(NULL);
current->ticks = times(¤t->tms_data);
if (current->ticks == (clock_t)-1) {
perror("获取CPU时间失败");
return -1;
}
// 计算CPU使用率(与前一个采样点比较)
if (monitor->history_count > 0) {
cpu_monitor_data_t *previous = &monitor->history[monitor->history_count - 1];
clock_t ticks_diff = current->ticks - previous->ticks;
if (ticks_diff > 0) {
clock_t utime_diff = current->tms_data.tms_utime - previous->tms_data.tms_utime;
clock_t stime_diff = current->tms_data.tms_stime - previous->tms_data.tms_stime;
clock_t cutime_diff = current->tms_data.tms_cutime - previous->tms_data.tms_cutime;
clock_t cstime_diff = current->tms_data.tms_cstime - previous->tms_data.tms_cstime;
current->user_cpu_percent = (double)utime_diff / ticks_diff * 100;
current->system_cpu_percent = (double)stime_diff / ticks_diff * 100;
current->children_cpu_percent = (double)(cutime_diff + cstime_diff) / ticks_diff * 100;
current->cpu_usage_percent = current->user_cpu_percent +
current->system_cpu_percent +
current->children_cpu_percent;
} else {
current->cpu_usage_percent = 0.0;
current->user_cpu_percent = 0.0;
current->system_cpu_percent = 0.0;
current->children_cpu_percent = 0.0;
}
} else {
// 第一次采样,无法计算使用率
current->cpu_usage_percent = 0.0;
current->user_cpu_percent = 0.0;
current->system_cpu_percent = 0.0;
current->children_cpu_percent = 0.0;
}
monitor->history_count++;
return 0;
}
/**
* 显示CPU监控数据
*/
void show_cpu_monitor_data(const cpu_monitor_t *monitor) {
if (monitor->history_count == 0) {
printf("暂无监控数据\n");
return;
}
const cpu_monitor_data_t *latest = &monitor->history[monitor->history_count - 1];
printf("=== CPU监控数据 ===\n");
printf("采样时间: %s", ctime(&latest->timestamp));
printf("CPU使用率: %.2f%%\n", latest->cpu_usage_percent);
printf(" 用户态: %.2f%%\n", latest->user_cpu_percent);
printf(" 系统态: %.2f%%\n", latest->system_cpu_percent);
printf(" 子进程: %.2f%%\n", latest->children_cpu_percent);
// 显示详细时间信息
printf("详细时间信息:\n");
printf(" 用户态时间: %.3f 秒\n",
(double)latest->tms_data.tms_utime / monitor->clk_tck);
printf(" 系统态时间: %.3f 秒\n",
(double)latest->tms_data.tms_stime / monitor->clk_tck);
printf(" 子进程用户态时间: %.3f 秒\n",
(double)latest->tms_data.tms_cutime / monitor->clk_tck);
printf(" 子进程系统态时间: %.3f 秒\n",
(double)latest->tms_data.tms_cstime / monitor->clk_tck);
}
/**
* 显示历史趋势
*/
void show_cpu_trend(const cpu_monitor_t *monitor) {
if (monitor->history_count < 2) {
printf("数据不足,无法显示趋势\n");
return;
}
printf("=== CPU使用率趋势 ===\n");
printf("%-20s %-8s %-8s %-8s %-8s\n",
"时间", "总CPU%", "用户%", "系统%", "子进程%");
printf("%-20s %-8s %-8s %-8s %-8s\n",
"----", "------", "----", "----", "-----");
// 显示最近10个采样点
int start_index = (monitor->history_count > 10) ?
monitor->history_count - 10 : 0;
for (int i = start_index; i < monitor->history_count; i++) {
const cpu_monitor_data_t *data = &monitor->history[i];
char time_str[20];
strftime(time_str, sizeof(time_str), "%H:%M:%S", localtime(&data->timestamp));
printf("%-20s %-8.1f %-8.1f %-8.1f %-8.1f\n",
time_str,
data->cpu_usage_percent,
data->user_cpu_percent,
data->system_cpu_percent,
data->children_cpu_percent);
}
}
/**
* 模拟被监控的工作进程
*/
void work_process(int work_id) {
printf("工作进程 %d (PID: %d) 启动\n", work_id, getpid());
// 执行不同类型的工作
for (int cycle = 0; cycle < 5; cycle++) {
printf("工作进程 %d: 执行周期 %d\n", work_id, cycle + 1);
// CPU密集型工作
volatile long sum = 0;
for (long i = 0; i < 50000000; i++) {
sum += i;
}
printf(" CPU工作完成,结果: %ld\n", sum);
// I/O工作
char filename[64];
snprintf(filename, sizeof(filename), "/tmp/work_%d_cycle_%d.tmp", work_id, cycle);
FILE *fp = fopen(filename, "w");
if (fp) {
for (int i = 0; i < 10000; i++) {
fprintf(fp, "工作数据 %d.%d\n", cycle, i);
}
fclose(fp);
unlink(filename);
}
sleep(2); // 休息一下
}
printf("工作进程 %d 完成\n", work_id);
exit(work_id);
}
/**
* 演示实时CPU监控
*/
int demo_real_time_cpu_monitoring() {
cpu_monitor_t monitor;
pid_t worker_pids[2];
int worker_count = 2;
printf("=== 实时CPU监控演示 ===\n");
// 初始化监控器
if (init_cpu_monitor(&monitor, 0) != 0) {
return -1;
}
// 创建工作进程
printf("创建 %d 个工作进程:\n", worker_count);
for (int i = 0; i < worker_count; i++) {
worker_pids[i] = fork();
if (worker_pids[i] == 0) {
work_process(i + 1);
} else if (worker_pids[i] > 0) {
printf(" 工作进程 %d: PID=%d\n", i + 1, worker_pids[i]);
} else {
perror("创建工作进程失败");
for (int j = 0; j < i; j++) {
kill(worker_pids[j], SIGKILL);
}
return -1;
}
}
// 开始监控
printf("\n开始实时监控 (30秒):\n");
time_t start_time = time(NULL);
while (difftime(time(NULL), start_time) < 30) {
// 收集CPU数据
if (collect_cpu_data(&monitor) != 0) {
printf("收集CPU数据失败\n");
break;
}
// 每5秒显示一次详细信息
if (((int)difftime(time(NULL), start_time)) % 5 == 0) {
show_cpu_monitor_data(&monitor);
// 每15秒显示一次趋势
if (((int)difftime(time(NULL), start_time)) % 15 == 0) {
show_cpu_trend(&monitor);
}
printf("---\n");
}
// 短暂休眠
usleep(500000); // 500ms
}
// 等待工作进程完成
printf("等待工作进程完成:\n");
for (int i = 0; i < worker_count; i++) {
int status;
pid_t finished_pid = waitpid(worker_pids[i], &status, 0);
if (finished_pid > 0) {
printf(" 工作进程 %d (PID=%d) 已完成,退出状态: %d\n",
WEXITSTATUS(status), finished_pid, WEXITSTATUS(status));
}
}
// 显示最终监控结果
printf("\n=== 最终监控结果 ===\n");
// 收集最终数据
collect_cpu_data(&monitor);
show_cpu_monitor_data(&monitor);
// 显示完整趋势
printf("\n完整CPU使用率趋势:\n");
show_cpu_trend(&monitor);
// 统计分析
if (monitor.history_count > 1) {
double max_cpu = 0, min_cpu = 100, avg_cpu = 0;
double total_cpu = 0;
int valid_samples = 0;
for (int i = 1; i < monitor.history_count; i++) {
double cpu_usage = monitor.history[i].cpu_usage_percent;
if (cpu_usage >= 0) { // 有效数据
if (cpu_usage > max_cpu) max_cpu = cpu_usage;
if (cpu_usage < min_cpu) min_cpu = cpu_usage;
total_cpu += cpu_usage;
valid_samples++;
}
}
if (valid_samples > 0) {
avg_cpu = total_cpu / valid_samples;
printf("\n=== 统计分析 ===\n");
printf("CPU使用率统计:\n");
printf(" 最高使用率: %.2f%%\n", max_cpu);
printf(" 最低使用率: %.2f%%\n", min_cpu);
printf(" 平均使用率: %.2f%%\n", avg_cpu);
if (avg_cpu > 80) {
printf(" 🚨 警告: 平均CPU使用率过高\n");
} else if (avg_cpu > 60) {
printf(" ⚠ 提醒: CPU使用率较高\n");
} else {
printf(" ✓ CPU使用率正常\n");
}
}
}
return 0;
}
int main() {
return demo_real_time_cpu_monitoring();
}
示例5:进程资源使用统计
#include <sys/times.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <time.h>
#include <sys/resource.h>
/**
* 进程资源使用统计结构
*/
typedef struct {
pid_t pid;
char process_name[256];
struct tms start_tms;
struct tms end_tms;
clock_t start_ticks;
clock_t end_ticks;
time_t start_time;
time_t end_time;
// CPU时间统计
double user_time_seconds;
double system_time_seconds;
double children_user_time_seconds;
double children_system_time_seconds;
double total_cpu_time_seconds;
double wall_clock_time_seconds;
double cpu_utilization_percent;
// 系统资源统计
long max_rss_kb; // 最大驻留集大小
long page_faults; // 页面错误次数
long voluntary_ctxt_switches; // 自愿上下文切换
long nonvoluntary_ctxt_switches; // 非自愿上下文切换
} process_resource_stats_t;
/**
* 初始化进程资源统计
*/
int init_process_resource_stats(process_resource_stats_t *stats, pid_t target_pid) {
memset(stats, 0, sizeof(process_resource_stats_t));
stats->pid = target_pid ? target_pid : getpid();
stats->start_time = time(NULL);
stats->start_ticks = times(&stats->start_tms);
if (stats->start_ticks == (clock_t)-1) {
perror("初始化进程资源统计失败");
return -1;
}
// 获取进程名称
char comm_path[256];
snprintf(comm_path, sizeof(comm_path), "/proc/%d/comm", stats->pid);
FILE *fp = fopen(comm_path, "r");
if (fp) {
if (fgets(stats->process_name, sizeof(stats->process_name), fp)) {
// 移除换行符
char *newline = strchr(stats->process_name, '\n');
if (newline) *newline = '\0';
}
fclose(fp);
} else {
snprintf(stats->process_name, sizeof(stats->process_name), "process_%d", stats->pid);
}
printf("进程资源统计初始化:\n");
printf(" 进程ID: %d\n", stats->pid);
printf(" 进程名称: %s\n", stats->process_name);
printf(" 启动时间: %s", ctime(&stats->start_time));
return 0;
}
/**
* 完成进程资源统计
*/
int finish_process_resource_stats(process_resource_stats_t *stats) {
long clk_tck = sysconf(_SC_CLK_TCK);
stats->end_time = time(NULL);
stats->end_ticks = times(&stats->end_tms);
if (stats->end_ticks == (clock_t)-1) {
perror("完成进程资源统计失败");
return -1;
}
// 计算CPU时间
clock_t utime_diff = stats->end_tms.tms_utime - stats->start_tms.tms_utime;
clock_t stime_diff = stats->end_tms.tms_stime - stats->start_tms.tms_stime;
clock_t cutime_diff = stats->end_tms.tms_cutime - stats->start_tms.tms_cutime;
clock_t cstime_diff = stats->end_tms.tms_cstime - stats->start_tms.tms_cstime;
stats->user_time_seconds = (double)utime_diff / clk_tck;
stats->system_time_seconds = (double)stime_diff / clk_tck;
stats->children_user_time_seconds = (double)cutime_diff / clk_tck;
stats->children_system_time_seconds = (double)cstime_diff / clk_tck;
stats->total_cpu_time_seconds = stats->user_time_seconds +
stats->system_time_seconds +
stats->children_user_time_seconds +
stats->children_system_time_seconds;
stats->wall_clock_time_seconds = (double)(stats->end_ticks - stats->start_ticks) / clk_tck;
if (stats->wall_clock_time_seconds > 0) {
stats->cpu_utilization_percent = (stats->total_cpu_time_seconds /
stats->wall_clock_time_seconds) * 100;
}
// 获取系统资源使用情况
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage) == 0) {
stats->max_rss_kb = usage.ru_maxrss; // 在Linux上以KB为单位
stats->page_faults = usage.ru_majflt;
stats->voluntary_ctxt_switches = usage.ru_nvcsw;
stats->nonvoluntary_ctxt_switches = usage.ru_nivcsw;
}
return 0;
}
/**
* 显示进程资源统计
*/
void show_process_resource_stats(const process_resource_stats_t *stats) {
printf("=== 进程资源使用统计 ===\n");
printf("进程信息:\n");
printf(" 进程ID: %d\n", stats->pid);
printf(" 进程名称: %s\n", stats->process_name);
printf(" 运行时间: %s 到 %s",
ctime(&stats->start_time), ctime(&stats->end_time));
printf("\nCPU时间统计:\n");
printf(" 用户态时间: %.3f 秒\n", stats->user_time_seconds);
printf(" 系统态时间: %.3f 秒\n", stats->system_time_seconds);
printf(" 子进程用户态时间: %.3f 秒\n", stats->children_user_time_seconds);
printf(" 子进程系统态时间: %.3f 秒\n", stats->children_system_time_seconds);
printf(" 总CPU时间: %.3f 秒\n", stats->total_cpu_time_seconds);
printf(" 墙钟时间: %.3f 秒\n", stats->wall_clock_time_seconds);
printf(" CPU利用率: %.2f%%\n", stats->cpu_utilization_percent);
printf("\n系统资源统计:\n");
printf(" 最大内存使用: %ld KB (%.2f MB)\n",
stats->max_rss_kb, stats->max_rss_kb / 1024.0);
printf(" 主要页面错误: %ld\n", stats->page_faults);
printf(" 自愿上下文切换: %ld\n", stats->voluntary_ctxt_switches);
printf(" 非自愿上下文切换: %ld\n", stats->nonvoluntary_ctxt_switches);
printf(" 总上下文切换: %ld\n", stats->voluntary_ctxt_switches +
stats->nonvoluntary_ctxt_switches);
}
/**
* 模拟不同类型的工作负载
*/
void simulate_workload(int workload_type, int intensity) {
switch (workload_type) {
case 1: // CPU密集型
printf("执行CPU密集型工作 (强度: %d)\n", intensity);
volatile long sum = 0;
for (long i = 0; i < intensity * 10000000L; i++) {
sum += i * i;
}
printf(" CPU工作完成,结果: %ld\n", sum);
break;
case 2: // I/O密集型
printf("执行I/O密集型工作 (强度: %d)\n", intensity);
for (int i = 0; i < intensity * 100; i++) {
char filename[64];
snprintf(filename, sizeof(filename), "/tmp/io_work_%d_%d.tmp", getpid(), i);
FILE *fp = fopen(filename, "w");
if (fp) {
for (int j = 0; j < 1000; j++) {
fprintf(fp, "测试数据 %d.%d\n", i, j);
}
fclose(fp);
unlink(filename);
}
}
printf(" I/O工作完成\n");
break;
case 3: // 内存密集型
printf("执行内存密集型工作 (强度: %d)\n", intensity);
size_t alloc_size = intensity * 1024 * 1024; // MB
char *buffer = malloc(alloc_size);
if (buffer) {
// 填充内存
memset(buffer, 0xAA, alloc_size);
// 访问内存
volatile long checksum = 0;
for (size_t i = 0; i < alloc_size; i += 1024) {
checksum += buffer[i];
}
printf(" 内存工作完成,校验和: %ld\n", checksum);
free(buffer);
} else {
printf(" 内存分配失败\n");
}
break;
default:
printf("未知工作负载类型: %d\n", workload_type);
break;
}
}
/**
* 演示进程资源使用统计
*/
int demo_process_resource_statistics() {
process_resource_stats_t stats;
long clk_tck = sysconf(_SC_CLK_TCK);
printf("=== 进程资源使用统计演示 ===\n");
printf("系统滴答率: %ld 滴答/秒\n", clk_tck);
// 初始化统计
if (init_process_resource_stats(&stats, 0) != 0) {
return -1;
}
printf("\n开始执行不同类型的工作负载:\n");
// 工作负载1: CPU密集型
printf("\n1. CPU密集型工作:\n");
simulate_workload(1, 5);
// 工作负载2: I/O密集型
printf("\n2. I/O密集型工作:\n");
simulate_workload(2, 3);
// 工作负载3: 内存密集型
printf("\n3. 内存密集型工作:\n");
simulate_workload(3, 100);
// 混合工作负载
printf("\n4. 混合工作负载:\n");
for (int i = 0; i < 3; i++) {
simulate_workload(1, 2); // 轻量CPU工作
simulate_workload(2, 1); // 轻量I/O工作
sleep(1);
}
// 完成统计
if (finish_process_resource_stats(&stats) != 0) {
return -1;
}
// 显示统计结果
printf("\n");
show_process_resource_stats(&stats);
// 详细分析
printf("\n=== 详细分析 ===\n");
// CPU使用分析
printf("CPU使用分析:\n");
if (stats.cpu_utilization_percent > 80) {
printf(" 🚨 CPU使用率极高 (%.1f%%)\n", stats.cpu_utilization_percent);
printf(" 建议检查是否存在无限循环或算法效率问题\n");
} else if (stats.cpu_utilization_percent > 50) {
printf(" ⚠ CPU使用率较高 (%.1f%%)\n", stats.cpu_utilization_percent);
printf(" 建议优化热点代码\n");
} else {
printf(" ✓ CPU使用率正常 (%.1f%%)\n", stats.cpu_utilization_percent);
}
// 内存使用分析
printf("\n内存使用分析:\n");
if (stats.max_rss_kb > 1024 * 1024) { // 超过1GB
printf(" 🚨 内存使用量巨大: %.2f GB\n", stats.max_rss_kb / (1024.0 * 1024.0));
printf(" 建议检查是否存在内存泄漏\n");
} else if (stats.max_rss_kb > 100 * 1024) { // 超过100MB
printf(" ℹ 内存使用量较大: %.2f MB\n", stats.max_rss_kb / 1024.0);
printf(" 建议监控内存增长趋势\n");
} else {
printf(" ✓ 内存使用量正常: %.2f MB\n", stats.max_rss_kb / 1024.0);
}
// I/O效率分析
printf("\nI/O效率分析:\n");
double io_efficiency = (double)stats.voluntary_ctxt_switches /
(stats.voluntary_ctxt_switches + stats.nonvoluntary_ctxt_switches + 1);
if (io_efficiency > 0.8) {
printf(" ✓ I/O效率良好 (%.1f%% 自愿切换)\n", io_efficiency * 100);
printf(" 表明程序很好地配合了I/O操作\n");
} else {
printf(" ℹ I/O效率一般 (%.1f%% 自愿切换)\n", io_efficiency * 100);
printf(" 可以考虑优化阻塞I/O操作\n");
}
// 性能建议
printf("\n=== 性能优化建议 ===\n");
printf("1. CPU优化:\n");
printf(" - 分析CPU密集型代码段\n");
printf(" - 考虑并行处理或算法优化\n");
printf(" - 使用性能分析工具定位热点\n");
printf("\n2. 内存优化:\n");
printf(" - 监控内存使用峰值\n");
printf(" - 及时释放不用的内存\n");
printf(" - 考虑内存池或对象复用\n");
printf("\n3. I/O优化:\n");
printf(" - 使用缓冲减少I/O次数\n");
printf(" - 考虑异步I/O操作\n");
printf(" - 优化文件访问模式\n");
return 0;
}
int main() {
return demo_process_resource_statistics();
}
times 使用注意事项
系统要求:
POSIX兼容 : 支持POSIX标准的系统
权限要求 : 通常不需要特殊权限
架构支持 : 支持所有主流架构
精度考虑:
滴答精度 : 受系统滴答率限制(通常100Hz)
累积误差 : 长时间监控可能累积误差
采样频率 : 高频采样可能影响被监控进程
错误处理:
返回值检查 : 必须检查返回值和errno
系统资源 : 可能在资源不足时失败
进程状态 : 目标进程终止时的行为
性能考虑:
系统调用开销 : 频繁调用有性能开销
内存使用 : 历史数据存储需要内存
监控开销 : 监控本身会消耗少量CPU资源
安全考虑:
权限检查 : 监控其他进程需要适当权限
资源限制 : 避免过度消耗系统资源
数据保护 : 监控数据的隐私和安全
最佳实践:
合理采样 : 选择适当的采样间隔
错误处理 : 妥善处理各种错误情况
资源管理 : 及时清理监控资源
数据持久化 : 重要监控数据应持久化存储
报警机制 : 设置合理的报警阈值
times函数特点
优点:
标准兼容 : POSIX标准函数,广泛支持
信息全面 : 提供完整的CPU时间统计
性能良好 : 系统调用开销小
易于使用 : API简单直观
限制:
精度限制 : 受系统滴答率限制
实时性 : 不是实时监控的最佳选择
跨进程 : 监控其他进程需要权限
历史数据 : 只能获取累积统计,不能获取瞬时值
相关函数对比
times vs clock:
// times(): 获取进程CPU时间统计
struct tms tms_buf;
clock_t ticks = times(&tms_buf);
// clock(): 获取进程CPU时间
clock_t cpu_time = clock();
times vs getrusage:
// times(): 基础CPU时间统计
struct tms tms_buf;
times(&tms_buf);
// getrusage(): 详细的资源使用情况
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
常见使用场景
1. 性能分析:
// 分析程序CPU使用情况
struct tms start_tms, end_tms;
clock_t start_ticks = times(&start_tms);
// 执行程序
clock_t end_ticks = times(&end_tms);
// 计算CPU时间差
2. 资源监控:
// 监控进程资源使用
while (monitoring) {
struct tms current_tms;
clock_t current_ticks = times(¤t_tms);
// 分析CPU使用率
sleep(1);
}
3. 系统管理:
// 系统负载监控
struct tms system_tms;
clock_t system_ticks = times(&system_tms);
// 分析系统整体性能
总结
times
函数是Linux系统中重要的进程资源监控工具,提供了:
全面的CPU时间统计 : 包括用户态、系统态和子进程时间
标准兼容性 : 符合POSIX标准,广泛支持
简单易用 : API设计直观,易于集成
性能监控 : 适用于各种性能分析场景
通过合理使用 times
函数,可以构建功能强大的性能监控和分析工具。在实际应用中,需要注意精度限制、错误处理和性能影响等问题,选择合适的监控策略和采样频率。
https://app-blog.csdn.net/csdn/aiChatNew
times 函数详解
1. 函数介绍
2. 函数原型
3. 功能
4. 参数
5. 返回值
6. 相似函数,或关联函数
7. 示例代码
示例1:基础times使用
示例2:父子进程CPU时间统计
示例3:性能分析工具
示例4:实时CPU监控
示例5:进程资源使用统计
times 使用注意事项
系统要求:
精度考虑:
错误处理:
性能考虑:
安全考虑:
最佳实践:
times函数特点
优点:
限制:
相关函数对比
times vs clock:
times vs getrusage:
常见使用场景
1. 性能分析:
2. 资源监控:
3. 系统管理:
总结
Markdown 27496 字数 1357 行数 当前行 1, 当前列 0
HTML 27105 字数 1120 段落
保存草稿 发布文章