linux-kernel-freqtable.c

本文详细介绍了Linux中用于处理CPU频率表的辅助函数,包括CPU信息读取、验证、目标频率寻找等功能。

/*
 * linux/drivers/cpufreq/freq_table.c
 *
 * Copyright (C) 2002 - 2003 Dominik Brodowski
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/cpufreq.h>

/*********************************************************************
 *                     FREQUENCY TABLE HELPERS                       *
 *********************************************************************/

int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,
        struct cpufreq_frequency_table *table)
{
 unsigned int min_freq = ~0;
 unsigned int max_freq = 0;
 unsigned int i;

 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  unsigned int freq = table[i].frequency;
  if (freq == CPUFREQ_ENTRY_INVALID) {
   pr_debug("table entry %u is invalid, skipping\n", i);

   continue;
  }
  pr_debug("table entry %u: %u kHz, %u index\n",
     i, freq, table[i].index);
  if (freq < min_freq)
   min_freq = freq;
  if (freq > max_freq)
   max_freq = freq;
 }

 policy->min = policy->cpuinfo.min_freq = min_freq;
 policy->max = policy->cpuinfo.max_freq = max_freq;

 if (policy->min == ~0)
  return -EINVAL;
 else
  return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_cpuinfo);


int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,
       struct cpufreq_frequency_table *table)
{
 unsigned int next_larger = ~0;
 unsigned int i;
 unsigned int count = 0;

 pr_debug("request for verification of policy (%u - %u kHz) for cpu %u\n",
     policy->min, policy->max, policy->cpu);

 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
         policy->cpuinfo.max_freq);

 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  unsigned int freq = table[i].frequency;
  if (freq == CPUFREQ_ENTRY_INVALID)
   continue;
  if ((freq >= policy->min) && (freq <= policy->max))
   count++;
  else if ((next_larger > freq) && (freq > policy->max))
   next_larger = freq;
 }

 if (!count)
  policy->max = next_larger;

 cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
         policy->cpuinfo.max_freq);

 pr_debug("verification lead to (%u - %u kHz) for cpu %u\n",
    policy->min, policy->max, policy->cpu);

 return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_verify);


int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
       struct cpufreq_frequency_table *table,
       unsigned int target_freq,
       unsigned int relation,
       unsigned int *index)
{
 struct cpufreq_frequency_table optimal = {
  .index = ~0,
  .frequency = 0,
 };
 struct cpufreq_frequency_table suboptimal = {
  .index = ~0,
  .frequency = 0,
 };
 unsigned int i;

 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n",
     target_freq, relation, policy->cpu);

 switch (relation) {
 case CPUFREQ_RELATION_H:
  suboptimal.frequency = ~0;
  break;
 case CPUFREQ_RELATION_L:
  optimal.frequency = ~0;
  break;
 }

 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  unsigned int freq = table[i].frequency;
  if (freq == CPUFREQ_ENTRY_INVALID)
   continue;
  if ((freq < policy->min) || (freq > policy->max))
   continue;
  switch (relation) {
  case CPUFREQ_RELATION_H:
   if (freq <= target_freq) {
    if (freq >= optimal.frequency) {
     optimal.frequency = freq;
     optimal.index = i;
    }
   } else {
    if (freq <= suboptimal.frequency) {
     suboptimal.frequency = freq;
     suboptimal.index = i;
    }
   }
   break;
  case CPUFREQ_RELATION_L:
   if (freq >= target_freq) {
    if (freq <= optimal.frequency) {
     optimal.frequency = freq;
     optimal.index = i;
    }
   } else {
    if (freq >= suboptimal.frequency) {
     suboptimal.frequency = freq;
     suboptimal.index = i;
    }
   }
   break;
  }
 }
 if (optimal.index > i) {
  if (suboptimal.index > i)
   return -EINVAL;
  *index = suboptimal.index;
 } else
  *index = optimal.index;

 pr_debug("target is %u (%u kHz, %u)\n", *index, table[*index].frequency,
  table[*index].index);

 return 0;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);

static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
/**
 * show_available_freqs - show available frequencies for the specified CPU
 */
static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf)
{
 unsigned int i = 0;
 unsigned int cpu = policy->cpu;
 ssize_t count = 0;
 struct cpufreq_frequency_table *table;

 if (!per_cpu(cpufreq_show_table, cpu))
  return -ENODEV;

 table = per_cpu(cpufreq_show_table, cpu);

 for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) {
  if (table[i].frequency == CPUFREQ_ENTRY_INVALID)
   continue;
  count += sprintf(&buf[count], "%d ", table[i].frequency);
 }
 count += sprintf(&buf[count], "\n");

 return count;

}

struct freq_attr cpufreq_freq_attr_scaling_available_freqs = {
 .attr = { .name = "scaling_available_frequencies",
    .mode = 0444,
  },
 .show = show_available_freqs,
};
EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs);

/*
 * if you use these, you must assure that the frequency table is valid
 * all the time between get_attr and put_attr!
 */
void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
          unsigned int cpu)
{
 pr_debug("setting show_table for cpu %u to %p\n", cpu, table);
 per_cpu(cpufreq_show_table, cpu) = table;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_get_attr);

void cpufreq_frequency_table_put_attr(unsigned int cpu)
{
 pr_debug("clearing show_table for cpu %u\n", cpu);
 per_cpu(cpufreq_show_table, cpu) = NULL;
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_put_attr);

void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy)
{
 pr_debug("Updating show_table for new_cpu %u from last_cpu %u\n",
   policy->cpu, policy->last_cpu);
 per_cpu(cpufreq_show_table, policy->cpu) = per_cpu(cpufreq_show_table,
   policy->last_cpu);
 per_cpu(cpufreq_show_table, policy->last_cpu) = NULL;
}

struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu)
{
 return per_cpu(cpufreq_show_table, cpu);
}
EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table);

MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
MODULE_DESCRIPTION("CPUfreq frequency table helpers");
MODULE_LICENSE("GPL");

<think>我们已知系统中存在的是 `linux-source-5.15.0.tar.bz2`,而用户尝试解压的是 `linux-source-6.8.0-85.tar.bz2`。因此,错误的原因是版本不匹配。 用户的上一条命令是:`tar xf linux-source-$(uname -r | sed 's/-generic//').tar.bz2` 而 `uname -r` 的输出可能是 `6.8.0-85-generic`,经过sed处理后变成 `6.8.0-85`,所以命令试图解压的文件名为 `linux-source-6.8.0-85.tar.bz2`,但实际系统中存在的是 `linux-source-5.15.0.tar.bz2`。 解决方案有两种: 1. 安装与当前运行内核版本匹配的源码包(即6.8.0-85对应的源码包),然后解压。 2. 如果系统中已安装的是5.15.0版本的源码包,那么应该使用这个存在的文件来解压。 但根据用户提供的信息,系统中存在的是`linux-source-5.15.0.tar.bz2`,而当前运行的内核版本是6.8.0-85?这不太可能,因为通常安装的源码包版本与运行的内核版本应该一致。所以我们需要先确认: 步骤1:确认当前运行的内核版本 步骤2:确认系统中已安装的源码包版本 用户已经通过`dpkg -l`和`ls`命令得知系统中存在`linux-source-5.15.0.tar.bz2`,那么我们需要检查当前运行的内核版本是否也是5.15.0?如果是,那么问题就是命令中sed的处理方式不正确。 分析命令:`uname -r | sed 's/-generic//'` 假设`uname -r`输出:`5.15.0-91-generic` 执行sed后:`5.15.0-91`,然后命令尝试解压`linux-source-5.15.0-91.tar.bz2`,但实际文件是`linux-source-5.15.0.tar.bz2`,所以不匹配。 因此,我们需要调整命令中的sed部分,去掉的是架构后缀(如-generic)以及可能的小版本号(如-91)?实际上,源码包的名字通常是主版本号(如5.15.0),不包含后面的小版本号。 所以正确的做法是:只保留主版本号(即前两部分数字,如5.15.0),去掉后面的所有内容。 我们可以使用如下命令获取主版本号: uname -r | sed -E 's/-[a-z]+-[0-9]+$//' # 结果会是5.15.0 或者更简单的: uname -r | cut -d '-' -f1,2 # 以-分割,取前两部分 但是注意,例如`5.15.0-91-generic`,取前两部分就是`5.15.0-91`,还是包含小版本号。而源码包名字是`linux-source-5.15.0.tar.bz2`,所以我们需要去掉小版本号。 实际上,源码包的版本号格式是:主版本.次版本.修订版本,后面的小版本号(如-91)是发行版自己加的,在源码包名字中不包含。 因此,我们需要从`uname -r`中提取出主版本号(即前三个数字部分)。然而,`uname -r`的输出可能是:5.15.0-91-generic,那么主版本号是5.15.0。 我们可以这样提取: uname -r | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-a-z0-9]*/\1/' 但更简单且安全的方法是:先去掉后缀(-generic等),然后去掉末尾的小版本号(即最后一个-后面的数字部分),但这样复杂。 其实,在安装源码包时,我们安装的是`linux-source-5.15.0`,所以文件名就是`linux-source-5.15.0.tar.bz2`。因此,我们只需要从`uname -r`中提取前三个数字(即5.15.0)即可。 但是,`uname -r`输出的第一个数字部分可能有不同的段数,例如4.4.0,或者5.15.0,或者6.8.0。所以我们可以这样: uname -r | sed 's/^\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/' 这个命令会匹配开头的数字.数字.数字,然后后面的内容全部去掉。 然而,在用户提供的例子中,运行内核版本是6.8.0-85?但系统中存在的源码包是5.15.0,这很奇怪。所以我们需要先确认: 执行:`uname -r` 得到什么?如果确实是6.8.0-85,那么系统中应该有linux-source-6.8.0.tar.bz2,但实际上用户只有5.15.0。 因此,更可能的情况是:用户使用的是5.15.0的内核,但`uname -r`输出的是5.15.0-xx-generic,而用户系统中存在的源码包是5.15.0版本的。 所以,我们建议用户先检查当前内核版本和已安装源码包版本是否匹配。 具体步骤: 1. 获取当前内核版本: current_kernel=$(uname -r) echo $current_kernel # 例如:5.15.0-91-generic 2. 从当前内核版本中提取主版本号(不带小版本号): main_version=$(echo $current_kernel | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/') # 或者:main_version=$(echo $current_kernel | cut -d '-' -f1,2 | cut -d '.' -f1-3) # 但注意:cut -d '-' -f1,2 得到的是5.15.0-91,然后我们还需要去掉-91?所以不如用sed。 3. 检查系统中是否存在该主版本号的源码包文件: ls /usr/src/linux-source-$main_version.tar.bz2 4. 如果存在,则解压: tar xf /usr/src/linux-source-$main_version.tar.bz2 但是,用户之前使用的命令是在当前目录下解压,而源码包实际在/usr/src/下,所以应该指定路径。 根据用户之前的错误信息,他是在当前目录下执行解压,但文件并不在当前目录,而是在/usr/src/下。 所以,正确的解压命令应该是: tar xf /usr/src/linux-source-$main_version.tar.bz2 因此,结合以上,我们可以写: tar xf /usr/src/linux-source-$(uname -r | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/').tar.bz2 但是,如果用户系统中存在的是5.15.0,而他的内核版本也是5.15.0-xx,那么这个命令就可以正确提取出5.15.0。 然而,用户之前尝试解压的是6.8.0-85,说明他的内核版本可能是6.8.0-85,但系统中没有这个版本的源码包,而有的是5.15.0。这可能是用户安装错了源码包版本?或者运行的内核版本与源码包版本不一致。 因此,我们需要先确认:当前运行的内核版本对应的源码包是否已安装? 如果用户希望使用当前运行内核的源码,那么应该安装对应版本的源码包。 如果用户希望使用系统中已存在的5.15.0源码包,那么他需要确保这是正确的版本(可能他就是要用5.15.0,而当前运行的内核是5.15.0,只是命令提取的版本号有问题)。 所以,我们分两种情况: 情况一:用户系统中已安装的源码包版本(5.15.0)正是当前运行内核的源码包(即当前内核版本是5.15.0系列) 解决方案:使用正确的提取主版本号的方式,并指定路径解压。 情况二:用户当前运行的内核版本是6.8.0,但系统中没有安装对应的源码包,只有5.15.0的源码包 解决方案:安装6.8.0的源码包,然后再解压。 步骤: 1. 确定当前内核版本: $ current_kernel=$(uname -r) $ echo $current_kernel 2. 如果输出是5.15.0-xx形式,那么我们可以用5.15.0的源码包。 $ sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 3. 如果输出是6.8.0-xx形式,那么需要安装6.8.0的源码包: $ sudo apt update $ sudo apt install linux-source-6.8.0 4. 然后解压新安装的源码包: $ sudo tar xf /usr/src/linux-source-6.8.0.tar.bz2 -C /usr/src/ 注意:源码包安装后位于/usr/src/目录下。 但是,用户之前执行命令时没有使用sudo,而且没有指定路径。所以,我们建议用户: - 确保源码包已经安装(通过apt) - 在/usr/src/目录下解压(因为源码包就在那里) 另外,用户原来的命令: tar xf linux-source-$(uname -r | sed 's/-generic//').tar.bz2 有两个问题: 1. 没有使用sudo(如果需要的话) 2. 没有指定路径(源码包在/usr/src下) 3. 版本号提取方式不对(应该提取主版本号,而不是简单去掉-generic) 因此,我们推荐的做法是: 步骤1:安装与当前内核版本对应的源码包(如果还未安装) 先获取主版本号: main_version=$(uname -r | grep -Po '^\d+\.\d+\.\d+') 然后安装: sudo apt install linux-source-$main_version 步骤2:解压源码包(在/usr/src目录下): sudo tar -xf /usr/src/linux-source-$main_version.tar.bz2 -C /usr/src/ 步骤3:创建符号链接(可选,方便使用): sudo ln -s /usr/src/linux-source-$main_version /usr/src/linux-$(uname -r | sed 's/-generic//') 注意:如果第二步解压时提示文件已存在(因为解压会生成一个目录),可以不用创建链接,或者根据需要使用。 现在,针对用户的情况(系统中已经有linux-source-5.15.0.tar.bz2,但当前内核版本未知),我们给出具体的诊断步骤: 1. 运行:`uname -r`,假设输出为:5.15.0-91-generic 2. 提取主版本号:5.15.0 3. 检查/usr/src/下是否存在linux-source-5.15.0.tar.bz2(用户说存在) 4. 解压:sudo tar -xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 因此,用户应该执行: sudo tar -xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 但是,如果用户当前内核版本是6.8.0,那么他需要安装6.8.0的源码包。 所以,我们首先确认当前内核版本: current_kernel=$(uname -r) main_version=$(echo $current_kernel | grep -Eo '^[0-9]+\.[0-9]+\.[0-9]+') 然后,检查源码包是否存在: if [ -f "/usr/src/linux-source-${main_version}.tar.bz2" ]; then sudo tar -xf "/usr/src/linux-source-${main_version}.tar.bz2" -C /usr/src/ else echo "需要先安装linux-source-${main_version}包" sudo apt install linux-source-${main_version} sudo tar -xf "/usr/src/linux-source-${main_version}.tar.bz2" -C /usr/src/ fi 但是,用户可能没有安装对应版本的源码包,所以第二步可能会失败,因此先安装。 因此,完整步骤如下: 1. 获取主版本号 2. 安装源码包(如果还没有安装) 3. 解压 由于用户已经明确系统中有linux-source-5.15.0.tar.bz2,但不知道当前内核版本,所以先确认当前内核版本。 如果当前内核版本的主版本号是5.15.0,那么直接解压即可。 如果当前内核版本的主版本号不是5.15.0,那么需要安装对应版本的源码包。 根据用户提供的信息,我们假设用户希望解压的是当前内核对应的源码包。 因此,我们给出两种解决方案: 解决方案一:如果用户当前运行的内核版本是5.15.0系列,则可以直接解压已存在的5.15.0源码包(注意版本号匹配,即主版本号相同) 步骤: 1. 确保当前内核版本主版本号为5.15.0(运行`uname -r`查看) 2. 执行解压:`sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/` 解决方案二:通用方法(推荐) 步骤: 1. 获取当前内核主版本号: main_version=$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') 2. 安装该版本的源码包(如果未安装): sudo apt update sudo apt install linux-source-${main_version} 3. 解压源码包到/usr/src/目录: sudo tar xf /usr/src/linux-source-${main_version}.tar.bz2 -C /usr/src/ 注意:第二步安装源码包后,源码包文件会出现在/usr/src/下。 如果用户系统中已经安装了该源码包,第二步会提示已经是最新版,不会重新下载。 根据用户的情况,他系统中已经有一个5.15.0的源码包,但当前内核版本可能是6.8.0?如果是这样,那么他需要安装6.8.0的源码包。 因此,我们建议用户采用通用方法。 总结命令如下: main_version=$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') sudo apt update sudo apt install linux-source-${main_version} sudo tar xf /usr/src/linux-source-${main_version}.tar.bz2 -C /usr/src/ 这样就能保证源码包版本与当前运行内核版本一致。 如果用户坚持使用已存在的5.15.0源码包,而不管当前运行的内核版本,那么可以直接解压: sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 但这样可能导致源码包版本与内核版本不一致,在后续操作(如编译模块)时可能出问题。 所以,我们推荐安装与当前运行内核版本一致的源码包。 注意:如果apt仓库中没有当前内核版本的源码包怎么办?这种情况可能需要手动下载源码。 因此,我们提供: 步骤三:如果安装失败(即apt找不到包),则手动下载: 手动下载地址:https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-${main_version}.tar.xz 然后解压到/usr/src/linux-${main_version}目录 但这里我们假设用户使用的是Ubuntu发行版,通常通过apt安装源码包。 最后,关于用户最初命令的修正: 不要在当前目录下执行,因为源码包在/usr/src下,而且需要root权限。 所以,用户最初命令可以修改为: sudo tar xf /usr/src/linux-source-$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+').tar.bz2 -C /usr/src/ 但前提是源码包已经存在。为了避免不存在的情况,建议先安装。 因此,我们给用户的最终建议是:按照通用方法安装并解压。 另外,如果用户只是想编译模块,那么还可以使用以下方法安装当前内核的源码: sudo apt install linux-headers-$(uname -r) 但这安装的是头文件,不是完整源码。 综上所述,我们给出详细的解决方案。 </think>### 解决 `tar xf` 解压时出现 "No such file or directory" 错误 根据您提供的信息(系统中存在 `linux-source-5.15.0.tar.bz2`,但命令尝试解压 `linux-source-6.8.0-85.tar.bz2`),问题原因是**内核版本不匹配**。以下是完整解决方案: --- ### 步骤 1:确认当前内核版本与源码包匹配 ```bash # 查看当前运行的内核版本 uname -r # 列出已安装的源码包 ls /usr/src | grep linux-source dpkg -l | grep linux-source ``` - 若输出显示当前内核为 `5.15.0-xx` 但源码包是 `linux-source-5.15.0.tar.bz2`,则版本匹配 - 若当前内核为 `6.8.0-xx` 但只有 `5.15.0` 源码包,需安装匹配的新源码包 --- ### 步骤 2:解决方案 A(版本匹配时) 当当前内核主版本为 `5.15.0` 时(如 `5.15.0-91-generic`): ```bash # 提取主版本号 (5.15.0) main_ver=$(uname -r | grep -Po '\d+\.\d+\.\d+') # 带路径解压源码包 sudo tar xf /usr/src/linux-source-${main_ver}.tar.bz2 -C /usr/src/ ``` $$ \text{解压路径} = \frac{\text{/usr/src}}{\text{kernel-source}} $$ --- ### 步骤 3:解决方案 B(版本不匹配时) 若当前内核是 `6.8.0-xx` 但缺少对应源码包: ```bash # 安装匹配的源码包 (示例为 6.8.0) main_ver=$(uname -r | grep -Po '\d+\.\d+\.\d+') sudo apt update sudo apt install linux-source-${main_ver} # 解压新安装的源码包 sudo tar xf /usr/src/linux-source-${main_ver}.tar.bz2 -C /usr/src/ ``` --- ### 关键原理说明 1. **版本号解析公式**: $$ \text{主版本号} = \lfloor \text{uname -r} \rfloor_{\text{前三位}} $$ - 命令 `uname -r | grep -Po '\d+\.\d+\.\d+'` 精确提取 `X.Y.Z` 格式主版本 2. **路径要求**: - 源码包默认位置:`/usr/src/linux-source-X.Y.Z.tar.bz2` - 必须使用绝对路径解压,否则会在当前目录查找[^2] 3. **版本一致性**: - 编译内核模块时源码版本必须与运行内核严格匹配 - 不匹配会导致模块加载失败或系统不稳定[^1] --- ### 验证解压结果 ```bash # 检查解压后的目录 ls -d /usr/src/linux-source-$(uname -r | grep -Po '\d+\.\d+\.\d+')* ``` ### 替代方案(若无对应源码包) ```bash # 1. 手动下载官方源码 wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.15.tar.xz # 2. 使用 apt-get source 获取 sudo apt-get build-dep linux-image-$(uname -r) sudo apt-get source linux-image-$(uname -r) ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值