Linux CPU频率文件详解:cpuinfo__freq 与 scaling_cur_freq

Linux CPU频率文件详解:cpuinfo_*_freqscaling_cur_freq

一、概述

在Linux系统中,/sys/devices/system/cpu/cpuX/cpufreq/ 目录下提供了多个用于查看和管理CPU频率的文件。其中,cpuinfo_max_freqcpuinfo_min_freqscaling_cur_freq 是最常被查看和对比的几个文件,它们分别代表了CPU的硬件能力实时运行状态

1. 核心概念

这三个文件可以清晰地分为两类:

  1. 能力范围(静态信息)cpuinfo_max_freqcpuinfo_min_freq
  2. 当前状态(动态信息)scaling_cur_freq

2. 能力范围文件(静态)

这两个文件描述了CPU硬件的固有属性,定义了频率调节的绝对边界。

1.cpuinfo_min_freq

  • 路径/sys/devices/system/cpu/cpuX/cpufreq/cpuinfo_min_freq
  • 含义 :该CPU核心在硬件设计和固件支持下,能够稳定运行的最低频率
  • 特性
    • 是一个静态的、不变的值
    • 代表了CPU的"设计规格"下限。
    • 操作系统和调频策略不能将频率设置得比这个值更低。

2.cpuinfo_max_freq

  • 路径/sys/devices/system/cpu/cpuX/cpufreq/cpuinfo_max_freq
  • 含义 :该CPU核心在硬件设计和固件支持下,能够稳定运行的最高频率(通常指基频或最大睿频频率)。
  • 特性
    • 是一个静态的、不变的值
    • 代表了CPU的"设计规格"上限。
    • 操作系统和调频策略不能将频率设置得比这个值更高。

三、当前状态文件(动态)

这个文件反映了CPU核心在运行时的实时状况。

scaling_cur_freq

  • 路径/sys/devices/system/cpu/cpuX/cpufreq/scaling_cur_freq
  • 含义 :显示该CPU核心此时此刻正在运行的实时频率
  • 特性
    • 是一个动态的、实时变化的值
    • 其变化范围被严格限制在 [cpuinfo_min_freq, cpuinfo_max_freq] 区间内。
    • 直接反映了当前CPU调频器(governor)的决策结果。
    • 会随着系统负载的变化而频繁波动。

四、类比理解

为了更好地理解,可以用汽车仪表盘进行类比:

Linux CPUFreq 文件 汽车仪表盘类比 说明
cpuinfo_max_freq 转速表红区车辆设计的最高时速 引擎能力的理论上限,不能也不应超过。
cpuinfo_min_freq 引擎能不熄火稳定运行的最低转速(怠速) 引擎能够稳定工作的下限。
scaling_cur_freq 当前时速表 显示了你此刻实际行驶的速度,会根据油门(负载)实时变化。

五、典型工作场景示例

假设某CPU核心(cpu0)的参数如下:

  • cpuinfo_min_freq = 800000 (800 MHz)
  • cpuinfo_max_freq = 3600000 (3.6 GHz)

系统运行过程:

  1. 系统启动后空闲时

    • scaling_cur_freq 可能显示为 800000(800 MHz)或略高,系统为省电将频率降至最低附近。
  2. 运行高负载任务时 (如编译软件 make -j4):

    • scaling_cur_freq 会迅速攀升,最终达到 3600000(3.6 GHz),系统全力工作以追求性能。
  3. 任务结束后

    • 几秒钟内,scaling_cur_freq 会逐渐下降回 800000(800 MHz)附近。

观察命令

你可以使用以下命令实时观察频率的动态变化:

bash 复制代码
# 每秒刷新一次 cpu0 的当前频率
watch -n 1 "cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"

六、扩展知识:scaling_*_freq 文件

在同一目录下,还有两个重要的管理性文件:

scaling_min_freqscaling_max_freq

  • 含义 :这是用户或系统策略允许 CPU调频器使用的软件频率范围
  • 特性
    • 它们默认分别等于 cpuinfo_min_freqcpuinfo_max_freq
    • 用户可以手动修改 这两个文件,来人为地限制CPU的频率范围,以实现特定的省电或降温目的。
    • 例如,将 scaling_max_freq 设置为 2000000(2.0 GHz),那么即使CPU硬件支持3.6 GHz,其 scaling_cur_freq 最高也只能达到2.0 GHz。

七、便捷脚本

bash 复制代码
#!/bin/bash

# CPU频率监控脚本 - 带超限检测
# 使用方法: ./cpu_freq_check.sh [刷新间隔(秒)]

INTERVAL=${1:-2}
CPU_COUNT=$(grep -c "^processor" /proc/cpuinfo)

# 获取终端行数
TERM_LINES=$(tput lines)

show_header() {
    # 使用转义序列清除屏幕并移动光标到左上角
    printf "\033[2J\033[H"
    echo "🔍 CPU频率监控 - 带超限检测"
    echo "=================================================================================="
    echo "时间: $(date "+%H:%M:%S") | 核心: ${CPU_COUNT} | 间隔: ${INTERVAL}s"
    echo "=================================================================================="
}

# 初始化:第一次显示完整界面
first_run=true

check_freq_limits() {
    local out_of_range_count=0
    local scaling_limit_count=0
    
    # 如果不是第一次运行,只移动光标到数据开始位置
    if [ "$first_run" = false ]; then
        # 移动到数据开始行(第6行)
        printf "\033[6H"
    else
        echo "核心    当前频率       硬件范围       scaling范围     状态"
        echo "------ ------------ -------------- -------------- ------------"
        first_run=false
    fi
    
    for ((cpu=0; cpu<CPU_COUNT; cpu++)); do
        cur_file="/sys/devices/system/cpu/cpu${cpu}/cpufreq/scaling_cur_freq"
        min_file="/sys/devices/system/cpu/cpu${cpu}/cpufreq/cpuinfo_min_freq"
        max_file="/sys/devices/system/cpu/cpu${cpu}/cpufreq/cpuinfo_max_freq"
        scaling_min_file="/sys/devices/system/cpu/cpu${cpu}/cpufreq/scaling_min_freq"
        scaling_max_file="/sys/devices/system/cpu/cpu${cpu}/cpufreq/scaling_max_freq"
        
        # 移动到该CPU行的开始位置
        printf "\033[%d;1H" $((8 + cpu))
        
        if [ -f "$cur_file" ]; then
            current=$(cat "$cur_file" 2>/dev/null)
            min_freq=$(cat "$min_file" 2>/dev/null)
            max_freq=$(cat "$max_file" 2>/dev/null)
            scaling_min=$(cat "$scaling_min_file" 2>/dev/null)
            scaling_max=$(cat "$scaling_max_file" 2>/dev/null)
            
            current_mhz=$((current/1000))
            min_mhz=$((min_freq/1000))
            max_mhz=$((max_freq/1000))
            scaling_min_mhz=$((scaling_min/1000))
            scaling_max_mhz=$((scaling_max/1000))
            
            # 检查状态
            status="✅ 正常"
            color="\033[32m"  # 绿色 - 正常
            
            # 检查是否超出硬件范围
            if [ $current -lt $min_freq ] || [ $current -gt $max_freq ]; then
                color="\033[31m"  # 红色 - 超出硬件范围
                status="⚠️  硬件超限"
                out_of_range_count=$((out_of_range_count + 1))
            # 检查是否超出scaling范围
            elif [ $current -lt $scaling_min ] || [ $current -gt $scaling_max ]; then
                color="\033[33m"  # 黄色 - 超出scaling范围
                status="⚠️  缩放超限"
                scaling_limit_count=$((scaling_limit_count + 1))
            fi
            
            # 清除当前行并输出新内容
            printf "\033[KCPU%-2d  ${color}%4d MHz\033[0m    %4d-%-4d MHz  %4d-%-4d MHz  ${status}\n" \
                   $cpu $current_mhz $min_mhz $max_mhz $scaling_min_mhz $scaling_max_mhz
        else
            # 清除当前行并输出离线状态
            printf "\033[KCPU%-2d    -- 离线 --     -- 离线 --     -- 离线 --     ⚫ 离线\n" $cpu
        fi
    done
    
    # 移动到统计信息行
    local stats_line=$((8 + CPU_COUNT))
    printf "\033[%d;1H" $stats_line
    printf "\033[K=================================================================================="
    
    local warning_count=$((out_of_range_count + scaling_limit_count))
    
    # 更新统计信息行
    printf "\033[%d;1H" $((stats_line + 1))
    printf "\033[K"  # 清除行
    
    if [ $warning_count -gt 0 ]; then
        if [ $out_of_range_count -gt 0 ]; then
            printf "\033[K🚨 严重: ${out_of_range_count}个核心频率超出硬件范围!\n"
        fi
        if [ $scaling_limit_count -gt 0 ]; then
            printf "\033[K⚠️  警告: ${scaling_limit_count}个核心频率超出scaling范围!\n"
        fi
    else
        printf "\033[K✅ 所有核心频率均在正常范围内\n"
    fi
    
    # 更新额外信息行
    local info_line=$((stats_line + 2))
    local current_line=$info_line
    
    # 检查Turbo Boost状态
    if [ -f "/sys/devices/system/cpu/intel_pstate/no_turbo" ]; then
        turbo_status=$(cat /sys/devices/system/cpu/intel_pstate/no_turbo)
        if [ "$turbo_status" = "0" ]; then
            printf "\033[%d;1H" $current_line
            printf "\033[K💡 提示: Intel Turbo Boost 已启用"
            current_line=$((current_line + 1))
        fi
    fi
    
    if [ -f "/sys/devices/system/cpu/cpufreq/boost" ]; then
        boost_status=$(cat /sys/devices/system/cpu/cpufreq/boost)
        if [ "$boost_status" = "1" ]; then
            printf "\033[%d;1H" $current_line
            printf "\033[K💡 提示: CPU频率加速已启用"
            current_line=$((current_line + 1))
        fi
    fi
    
    # 显示scaling governor信息
    governor_file="/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
    if [ -f "$governor_file" ]; then
        governor=$(cat "$governor_file" 2>/dev/null)
        printf "\033[%d;1H" $current_line
        printf "\033[K🎛️  当前调频策略: ${governor}"
        current_line=$((current_line + 1))
    fi

    # 显示可用调频策略信息
    available_governors_file="/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors"
    if [ -f "$available_governors_file" ]; then
        available_governors=$(cat "$available_governors_file" 2>/dev/null)
        printf "\033[%d;1H" $current_line
        printf "\033[K📋 可用调频策略: ${available_governors}"
        current_line=$((current_line + 1))
    fi    

    # 显示系统负载
    if command -v uptime >/dev/null 2>&1; then
        load_avg=$(uptime | awk -F'load average:' '{print $2}')
        printf "\033[%d;1H" $current_line
        printf "\033[K📊 系统负载:${load_avg}"
        current_line=$((current_line + 1))
    fi
    
    # 清除剩余的可能旧内容
    for ((line=current_line; line<=TERM_LINES; line++)); do
        printf "\033[%d;1H" $line
        printf "\033[K"
    done
    
    # 移动光标到最后,避免闪烁
    printf "\033[%d;1H" $TERM_LINES
}

# 获取CPU型号
CPU_MODEL=$(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | sed 's/^ *//')

# 初始显示
show_header
echo "CPU: ${CPU_MODEL}"
echo "开始监控,按 Ctrl+C 停止..."
echo "核心    当前频率       硬件范围       scaling范围     状态"
echo "------ ------------ -------------- -------------- ------------"

trap 'printf "\033[?25h\033[%d;1H\n监控结束\n" $((8 + CPU_COUNT + 10)); exit 0' INT TERM

# 显示光标并设置退出时恢复
printf "\033[?25l"

while true; do
    check_freq_limits
    sleep $INTERVAL
done
相关推荐
A小辣椒16 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒20 小时前
TShark:基础知识
linux
AlfredZhao1 天前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao2 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush43 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5203 天前
Linux 11 动态监控指令top
linux