前言
简单介绍一下cpu的使用率是怎么来的。
正文
cpu 使用大概有这几方面:- public class CpuTimeBreakdown
- {
- // 1. 用户时间 (User Time)
- // - 应用程序在用户态执行的时间
- // - 包括:业务逻辑、算法计算、数据处理
- public long UserTime { get; set; }
-
- // 2. 系统时间 (System Time)
- // - 应用程序在内核态执行的时间
- // - 包括:系统调用、内存管理、进程调度
- public long SystemTime { get; set; }
-
- // 3. 空闲时间 (Idle Time)
- // - CPU真正空闲的时间
- // - 包括:HALT指令、节能模式、等待中断
- public long IdleTime { get; set; }
-
- // 4. I/O等待时间 (I/O Wait Time)
- // - CPU等待I/O设备的时间
- // - 包括:磁盘I/O、网络I/O、设备I/O
- public long IoWaitTime { get; set; }
-
- // 5. 中断时间 (IRQ Time)
- // - 处理硬件中断的时间
- // - 包括:网络中断、磁盘中断、定时器中断
- public long IrqTime { get; set; }
-
- // 6. 软中断时间 (Soft IRQ Time)
- // - 处理软中断的时间
- // - 包括:网络包处理、定时器处理、调度器中断
- public long SoftIrqTime { get; set; }
-
- // 7. 虚拟化时间 (Steal Time)
- // - 被虚拟机监控器占用的时间
- public long StealTime { get; set; }
- }
复制代码 然后计算公式如下:- public class CpuUsageCalculator
- {
- public static CpuUsageBreakdown CalculateCpuUsage(CpuTimeSnapshot current, CpuTimeSnapshot previous)
- {
- var totalDiff = current.TotalTime - previous.TotalTime;
-
- return new CpuUsageBreakdown
- {
- // 总CPU使用率 = (总时间 - 空闲时间 - I/O等待时间) / 总时间
- TotalUsage = (double)(totalDiff - current.IdleTime + previous.IdleTime -
- current.IoWaitTime + previous.IoWaitTime) / totalDiff * 100,
-
- // 用户态使用率
- UserUsage = (double)(current.UserTime - previous.UserTime) / totalDiff * 100,
-
- // 系统态使用率
- SystemUsage = (double)(current.SystemTime - previous.SystemTime) / totalDiff * 100,
-
- // 中断使用率
- IrqUsage = (double)(current.IrqTime + current.SoftIrqTime -
- previous.IrqTime - previous.SoftIrqTime) / totalDiff * 100,
-
- // I/O等待率
- IoWaitUsage = (double)(current.IoWaitTime - previous.IoWaitTime) / totalDiff * 100,
-
- // 空闲率
- IdleUsage = (double)(current.IdleTime - previous.IdleTime) / totalDiff * 100
- };
- }
- }
复制代码 这里就有人问了,cpu 为啥会有空闲时间呢? cpu 应该是一直会运行的,那么这个空闲时间是什么呢?- public class IdleTimeExplanation
- {
- public static void ExplainIdleTime()
- {
- Console.WriteLine("CPU空闲时间包括:");
- Console.WriteLine("1. HALT指令执行时间 - CPU进入低功耗状态");
- Console.WriteLine("2. 等待中断的时间 - 没有可执行的任务");
- Console.WriteLine("3. 节能模式时间 - CPU降频或休眠");
- Console.WriteLine("4. 调度器空闲时间 - 没有就绪进程");
- Console.WriteLine("5. 内核空闲循环 - 执行idle进程");
- }
- }
复制代码 在操作系统重,会执行idle 进程,不让cpu空闲下来,这个是为了让cpu不脱离操作系统的控制。- // Linux内核中的空闲进程
- public class IdleProcess
- {
- public static void IdleLoop()
- {
- while (true)
- {
- // 1. 检查是否有就绪进程
- if (HasReadyProcess())
- {
- ScheduleNextProcess();
- break;
- }
-
- // 2. 执行HALT指令,进入低功耗状态
- HaltCpu();
-
- // 3. 等待中断唤醒
- WaitForInterrupt();
-
- // 4. 处理中断
- HandleInterrupt();
- }
- }
-
- private static void HaltCpu()
- {
- // 执行HLT指令,CPU进入低功耗状态
- // 但CPU仍然可以响应中断
- }
- }
复制代码 那么这里的软中断和硬中断是怎么占用cpu的时间的?
按照我们的思维上来说,处理软中断和硬中断呢? 理论上cpu只是会找到特定的程序的位置,但是处理算是系统处理,应该算在系统上吧。
那么我们看一下定义:系统时间是什么定义:
系统时间是应用程序在内核态执行的时间。
那么这里看到,其实内核调用呢?分为两个部分一个是系统时间,一个是中断时间。- public class InterruptVsSystemTime
- {
- public static void ExplainDifference()
- {
- Console.WriteLine("中断时间 vs 系统时间的区别:");
- Console.WriteLine();
- Console.WriteLine("系统时间 (System Time):");
- Console.WriteLine("- 应用程序主动发起的系统调用");
- Console.WriteLine("- 进程在用户态主动调用内核函数");
- Console.WriteLine("- 例如:read(), write(), malloc()");
- Console.WriteLine("- 进程知道何时开始和结束");
- Console.WriteLine();
- Console.WriteLine("中断时间 (IRQ Time):");
- Console.WriteLine("- 硬件设备强制中断当前执行");
- Console.WriteLine("- CPU被动响应中断信号");
- Console.WriteLine("- 例如:网卡中断、磁盘中断");
- Console.WriteLine("- 进程不知道何时发生中断");
- Console.WriteLine("- 中断处理程序在内核态执行");
- }
- }
复制代码 执行的上下文也不同 :- public class ExecutionContext
- {
- public static void DemonstrateContext()
- {
- Console.WriteLine("执行上下文对比:");
- Console.WriteLine();
- Console.WriteLine("系统调用上下文:");
- Console.WriteLine("用户进程 -> 系统调用 -> 内核函数 -> 返回用户进程");
- Console.WriteLine("主动发起,可预测,进程控制");
- Console.WriteLine();
- Console.WriteLine("中断处理上下文:");
- Console.WriteLine("用户进程 -> 硬件中断 -> 中断处理程序 -> 返回用户进程");
- Console.WriteLine("被动响应,不可预测,硬件控制");
- }
- }
复制代码 那么同样有人会疑问了,硬中断是硬件中断的,软中断是软件中断的? 真的是这个概念吗? 如果是这样,系统调用不也是软中断嘛?
那么来看一下系统调用和软中断的区别:
1.1 基本概念对比- public class SystemCallVsSoftInterrupt
- {
- public static void ExplainDifference()
- {
- Console.WriteLine("系统调用 vs 软中断:");
- Console.WriteLine();
- Console.WriteLine("系统调用 (System Call):");
- Console.WriteLine("- 用户程序主动发起的请求");
- Console.WriteLine("- 通过特定的指令序列触发");
- Console.WriteLine("- 进程知道何时发生");
- Console.WriteLine("- 同步执行");
- Console.WriteLine("- 例如:read(), write(), malloc()");
- Console.WriteLine();
- Console.WriteLine("软中断 (Soft IRQ):");
- Console.WriteLine("- 内核或硬件触发的异步事件");
- Console.WriteLine("- 通过设置标志位触发");
- Console.WriteLine("- 进程不知道何时发生");
- Console.WriteLine("- 异步执行");
- Console.WriteLine("- 例如:网络包处理、定时器处理");
- }
- }
复制代码 1.2 触发机制的不同- ; 系统调用的触发机制
- system_call:
- ; 1. 用户程序执行syscall指令
- syscall
-
- ; 2. CPU自动切换到内核态
- ; 3. 跳转到系统调用处理程序
- ; 4. 执行系统调用逻辑
- ; 5. 返回用户态
- ; 软中断的触发机制
- soft_irq:
- ; 1. 内核或硬件设置软中断标志
- set_bit(SOFTIRQ_BIT, &softirq_pending)
-
- ; 2. 在适当时机检查软中断标志
- ; 3. 执行软中断处理程序
- ; 4. 清除软中断标志
复制代码 软中断流程:- public class SoftInterruptFlow
- {
- public static void DemonstrateSoftInterrupt()
- {
- Console.WriteLine("软中断执行流程:");
- Console.WriteLine();
- Console.WriteLine("触发阶段:");
- Console.WriteLine("1. 硬件中断处理程序设置软中断标志");
- Console.WriteLine("2. 硬件中断处理完成");
- Console.WriteLine("3. 返回被中断的进程");
- Console.WriteLine();
- Console.WriteLine("执行阶段:");
- Console.WriteLine("4. 内核在适当时机检查软中断标志");
- Console.WriteLine("5. 发现有待处理的软中断");
- Console.WriteLine("6. 执行软中断处理程序");
- Console.WriteLine("7. 清除软中断标志");
- Console.WriteLine();
- Console.WriteLine("特点:异步、不可预测、内核控制");
- }
- }
复制代码 软中断的实现:- // Linux内核软中断实现
- void do_softirq(void)
- {
- unsigned long pending;
-
- // 获取待处理的软中断
- pending = local_softirq_pending();
-
- if (pending) {
- // 执行软中断处理程序
- if (pending & (1 << NET_RX_SOFTIRQ))
- net_rx_action();
-
- if (pending & (1 << TIMER_SOFTIRQ))
- run_timer_softirq();
-
- if (pending & (1 << TASKLET_SOFTIRQ))
- tasklet_action();
- }
- }
复制代码 大概就是这样一个过程:- public class HardInterrupt
- {
- public static void ExplainHardInterrupt()
- {
- Console.WriteLine("硬中断 (Hard IRQ):");
- Console.WriteLine();
- Console.WriteLine("定义:");
- Console.WriteLine("- 由硬件设备直接发送到CPU的中断信号");
- Console.WriteLine("- CPU必须立即响应的紧急事件");
- Console.WriteLine("- 具有最高优先级");
- Console.WriteLine("- 可以打断任何正在执行的代码");
- Console.WriteLine();
- Console.WriteLine("特点:");
- Console.WriteLine("- 硬件触发");
- Console.WriteLine("- 立即响应");
- Console.WriteLine("- 不可屏蔽(某些情况下)");
- Console.WriteLine("- 执行时间短");
- }
- }
复制代码 结
这里介绍了cpu的使用率是怎么回事,里面介绍了应用时间、系统时间、中断时间、空闲时间的概念,和他们之间的去呗,更有利于排查cpu高的问题,或者cpu不高,但是系统很慢,了解这些概念后,就容易根据这几个方面去排查。
来源:豆瓜网用户自行投稿发布,如果侵权,请联系站长删除 |