cpufreq_schedutil.c詳細(xì)解讀

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include "sched.h"

#include <linux/sched/cpufreq.h>
#include <trace/events/power.h>
#include <trace/hooks/sched.h>

#define IOWAIT_BOOST_MIN    (SCHED_CAPACITY_SCALE / 8)

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt:

這行定義了一個(gè)宏,用于格式化內(nèi)核日志輸出。它會在日志消息前自動加上模塊名(KBUILD_MODNAME)和冒號。例如,如果模塊名叫 sched,調(diào)用 pr_info("測試") 會輸出 sched: 測試。這是 Linux 內(nèi)核中常見的日志標(biāo)識方式。

#include "sched.h":
包含 Linux 內(nèi)核調(diào)度器的內(nèi)部頭文件,提供了調(diào)度相關(guān)的函數(shù)、數(shù)據(jù)結(jié)構(gòu)(如 task_struct)等定義。

#include <linux/sched/cpufreq.h>:
包含 CPU 頻率調(diào)整相關(guān)的頭文件,提供調(diào)度器與 CPU 頻率管理(cpufreq)交互的接口,比如請求頻率提升。

#include <trace/events/power.h>:
包含電源管理相關(guān)的跟蹤點(diǎn)定義,用于記錄 CPU 頻率變化或空閑狀態(tài)等事件,便于調(diào)試和性能分析。

#include <trace/hooks/sched.h>:
包含調(diào)度器事件的跟蹤鉤子,允許在不修改核心代碼的情況下,添加自定義跟蹤或回調(diào)功能來監(jiān)控調(diào)度行為。

#define IOWAIT_BOOST_MIN (SCHED_CAPACITY_SCALE / 8):
定義了 I/O 等待任務(wù)的最小頻率提升值。SCHED_CAPACITY_SCALE 通常是 1024,表示 CPU 的最大容量。

因此,IOWAIT_BOOST_MIN = 1024 / 8 = 128,表示為等待 I/O 的任務(wù)提供至少 1/8 的 CPU 性能提升(比如提高 CPU 頻率)。

整體作用

sugov_tunables 結(jié)構(gòu)體

struct sugov_tunables {
    struct gov_attr_set attr_set;
    unsigned int rate_limit_us;
};

struct gov_attr_set attr_set;
這是一個(gè)嵌入的結(jié)構(gòu)體,類型為 gov_attr_set,通常用于管理調(diào)度器頻率調(diào)節(jié)器的可調(diào)參數(shù)(tunables)。
它提供了內(nèi)核模塊與用戶空間交互的接口,允許通過 sysfs 文件系統(tǒng)動態(tài)調(diào)整參數(shù)(例如,讀取或設(shè)置頻率調(diào)節(jié)策略)。
具體來說,attr_set 包含一組屬性(attributes),用于存儲和管理參數(shù)的集合。
unsigned int rate_limit_us;
這是一個(gè)無符號整數(shù),表示頻率調(diào)整的速率限制,單位是微秒(us)。
它控制 schedutil 調(diào)度器多久調(diào)整一次 CPU 頻率,以避免過于頻繁的頻率變化(減少開銷和抖動)。
例如,如果 rate_limit_us 設(shè)置為 10000,則頻率調(diào)整至少間隔 10 毫秒。

sugov_policy 結(jié)構(gòu)體

struct sugov_policy {
//指向關(guān)聯(lián)的 CPU 頻率策略,包含頻率范圍(最小/最大頻率)、當(dāng)前頻率等信息。
//每個(gè) sugov_policy 對應(yīng)一組 CPU 核心的頻率管理策略。
    struct cpufreq_policy   *policy;
//指向 sugov_tunables 結(jié)構(gòu)體,存儲可調(diào)參數(shù)(如 rate_limit_us),用于配置頻率調(diào)整行為。
    struct sugov_tunables   *tunables;
//鏈表節(jié)點(diǎn),將該 sugov_policy 加入全局 tunables 鏈表,便于管理多個(gè)策略的調(diào)諧參數(shù)。
    struct list_head    tunables_hook;
//自旋鎖,保護(hù)共享策略(多核共享同一頻率策略)時(shí)的頻率更新操作,確保線程安全。
    raw_spinlock_t      update_lock;    /* For shared policies */
//上次頻率更新的時(shí)間(納秒),用于計(jì)算下次更新的時(shí)間間隔。
    u64         last_freq_update_time;
//頻率更新的最小時(shí)間間隔(納秒),基于 tunables->rate_limit_us,避免頻繁調(diào)整頻率。
    s64         freq_update_delay_ns;
//計(jì)劃設(shè)置的下一個(gè) CPU 頻率(kHz),在下次更新時(shí)應(yīng)用。
    unsigned int        next_freq;
//緩存的原始頻率值,用于優(yōu)化頻率計(jì)算或避免重復(fù)處理。
    unsigned int        cached_raw_freq;

    /* The next fields are only needed if fast switch cannot be used: */
//以下字段僅在不支持快速頻率切換(fast switch)時(shí)使用:
//中斷上下文中的異步工作,用于觸發(fā)頻率調(diào)整。
    struct          irq_work irq_work;
//內(nèi)核線程的工作項(xiàng),用于異步執(zhí)行頻率調(diào)整。
    struct          kthread_work work;
//互斥鎖,保護(hù)工作項(xiàng)的并發(fā)訪問。
    struct          mutex work_lock;
//內(nèi)核線程工作者,負(fù)責(zé)執(zhí)行頻率調(diào)整任務(wù)。
    struct          kthread_worker worker;
//指向執(zhí)行頻率調(diào)整的內(nèi)核線程。
    struct task_struct  *thread;
//標(biāo)志位,表示頻率調(diào)整是否正在進(jìn)行,防止重復(fù)調(diào)度。
    bool            work_in_progress;
//標(biāo)志位,表示頻率限制(如最大/最小頻率)是否改變,需重新評估頻率。
    bool            limits_changed;
//標(biāo)志位,表示是否需要更新頻率(例如,負(fù)載變化觸發(fā))。
    bool            need_freq_update;
};

sugov_cpu 結(jié)構(gòu)體

struct sugov_cpu {
//指向用于更新 CPU 利用率數(shù)據(jù)的結(jié)構(gòu)體,包含回調(diào)函數(shù)(如 update_util),
//由調(diào)度器調(diào)用以通知 schedutil 關(guān)于 CPU 負(fù)載的變化。
//它幫助 schedutil 根據(jù)任務(wù)負(fù)載調(diào)整 CPU 頻率。
    struct update_util_data update_util;
//指向該 CPU 關(guān)聯(lián)的 sugov_policy 結(jié)構(gòu)體,包含頻率策略和調(diào)諧參數(shù)(如 tunables)。
//一個(gè) sugov_policy 可能管理多個(gè) CPU(共享策略),而 sugov_cpu 是單個(gè) CPU 的數(shù)據(jù)。
    struct sugov_policy *sg_policy;
//該結(jié)構(gòu)對應(yīng)的 CPU 核心編號,用于標(biāo)識特定的 CPU。
    unsigned int        cpu;
//標(biāo)志位,表示是否有等待應(yīng)用的 I/O 提升(boost)。用于延遲應(yīng)用 I/O 提升以優(yōu)化性能。
    bool            iowait_boost_pending;
//當(dāng)前為 I/O 等待任務(wù)設(shè)置的頻率提升值(基于 SCHED_CAPACITY_SCALE,如您之前提到的 IOWAIT_BOOST_MIN = SCHED_CAPACITY_SCALE / 8)。
//它確保 I/O 密集型任務(wù)在調(diào)度時(shí)獲得更高的 CPU 頻率以減少延遲。
    unsigned int        iowait_boost;
//上次利用率更新的時(shí)間(納秒),用于跟蹤 CPU 負(fù)載變化的時(shí)機(jī)。
    u64         last_update;
//表示該 CPU 上 deadline 調(diào)度類任務(wù)的帶寬需求(bandwidth for deadline tasks)。
//用于確保實(shí)時(shí)任務(wù)的頻率需求得到滿足。
    unsigned long       bw_dl;
//該 CPU 的最大容量(通常基于 SCHED_CAPACITY_SCALE),表示硬件支持的最大性能。
    unsigned long       max;

    /* The field below is for single-CPU policies only: */
#ifdef CONFIG_NO_HZ_COMMON
//保存的空閑調(diào)用計(jì)數(shù),用于支持動態(tài)時(shí)鐘(tickless)系統(tǒng)。
//在單 CPU 策略中,記錄 CPU 進(jìn)入空閑狀態(tài)的次數(shù),幫助優(yōu)化能耗(與 NO_HZ 機(jī)制相關(guān))。
    unsigned long       saved_idle_calls;
#endif
};

DEFINE_PER_CPU

static DEFINE_PER_CPU(struct sugov_cpu, sugov_cpu);
DEFINE_PER_CPU:
這是一個(gè) Linux 內(nèi)核宏,用于為每個(gè) CPU 核心分配一個(gè)獨(dú)立的 struct sugov_cpu 實(shí)例。
struct sugov_cpu:
如您之前提供的定義,struct sugov_cpu 存儲單個(gè) CPU 核心的頻率調(diào)整狀態(tài),包括利用率數(shù)據(jù)(update_util)、I/O 提升(iowait_boost)、上次更新時(shí)間(last_update)等。
sugov_cpu:
這是變量的名稱,定義了一個(gè)全局的每 CPU 變量,供 schedutil 代碼訪問每個(gè) CPU 的 sugov_cpu 實(shí)例。
例如,CPU0 的 sugov_cpu 數(shù)據(jù)獨(dú)立于 CPU1 的數(shù)據(jù)。
static:
表示該變量具有文件作用域,僅在定義它的源文件中可見,防止外部模塊直接訪問。

sugov_should_update_freq結(jié)構(gòu)體

static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
{
    s64 delta_ns;
     //檢查當(dāng)前 CPU 是否支持頻率更新(通過 cpufreq_this_cpu_can_update)。
     //如果硬件不支持跨 CPU 頻率請求(例如,快速切換平臺無法處理遠(yuǎn)程 CPU 的請求),
     //直接返回 false,避免無意義的頻率計(jì)算。
    if (!cpufreq_this_cpu_can_update(sg_policy->policy))
        return false;
//檢查 limits_changed 標(biāo)志(sugov_policy 字段),表示頻率限制(如最大/最小頻率)是否發(fā)生變化。
//如果 limits_changed 為 true:清除標(biāo)志(limits_changed = false)。
//設(shè)置 need_freq_update = true,標(biāo)記需要頻率更新。
//直接返回 true,觸發(fā)頻率調(diào)整。
//unlikely 提示編譯器此條件不常發(fā)生,優(yōu)化分支預(yù)測。
    if (unlikely(sg_policy->limits_changed)) {
        sg_policy->limits_changed = false;
        sg_policy->need_freq_update = true;
        return true;
    }
//計(jì)算當(dāng)前時(shí)間與上次頻率更新時(shí)間(last_freq_update_time)的差值(納秒)。
//last_freq_update_time 是 sugov_policy 字段,記錄上次 記錄上次頻率調(diào)整的時(shí)間。
    delta_ns = time - sg_policy->last_freq_update_time;
//比較時(shí)間差 delta_ns 與頻率更新間隔 freq_update_delay_ns(sugov_policy 字段,基于 tunables->rate_limit_us)。
//如果 delta_ns 大于或等于 freq_update_delay_ns,返回 true,表示需要更新頻率;否則返回 false。
    return delta_ns >= sg_policy->freq_update_delay_ns;
 }

sugov_update_next_freq

//sg_policy:指向 struct sugov_policy,包含頻率策略相關(guān)數(shù)據(jù)(如 next_freq、last_freq_update_time)。
//time:當(dāng)前時(shí)間(納秒),用于更新頻率調(diào)整時(shí)間戳。
//next_freq:建議的下一個(gè) CPU 頻率(kHz)。
static bool sugov_update_next_freq(struct sugov_policy *sg_policy, u64 time,
                   unsigned int next_freq)
{
//檢查 need_freq_update 標(biāo)志(sugov_policy 字段),表示是否需要強(qiáng)制更新頻率(例如,負(fù)載變化或限制更改)。
//如果 need_freq_update 為 false(不需要強(qiáng)制更新):
//檢查當(dāng)前 next_freq(sg_policy->next_freq)是否與建議的 next_freq 相同。
//如果相同,返回 false,表示無需更新頻率(優(yōu)化,避免重復(fù)設(shè)置)。

    if (!sg_policy->need_freq_update) {
        if (sg_policy->next_freq == next_freq)
            return false;
    } else {
    //如果 need_freq_update 為 true(需要強(qiáng)制更新):
//調(diào)用 cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS),檢查硬件驅(qū)動是否要求更新頻率限制(如最大/最小頻率)。
//更新 need_freq_update 標(biāo)志,決定后續(xù)是否繼續(xù)需要強(qiáng)制更新。
//這確保在頻率限制變化時(shí)(如用戶調(diào)整 sysfs 參數(shù)),頻率更新符合硬件要求。
        sg_policy->need_freq_update = cpufreq_driver_test_flags(CPUFREQ_NEED_UPDATE_LIMITS);
    }
//將建議的 next_freq 存儲到 sugov_policy->next_freq,作為下次頻率調(diào)整的目標(biāo)值。
    sg_policy->next_freq = next_freq;
//更新 last_freq_update_time 為當(dāng)前時(shí)間,記錄頻率更新的時(shí)間戳。
//這與 sugov_should_update_freq 中的時(shí)間間隔檢查(freq_update_delay_ns)相關(guān)。
    sg_policy->last_freq_update_time = time;
//返回 true,表示頻率已更新(或需要應(yīng)用),通知調(diào)用者繼續(xù)處理(如觸發(fā) cpufreq 驅(qū)動調(diào)整頻率)。
    return true;
}

sugov_fast_switch

static void sugov_fast_switch(struct sugov_policy *sg_policy, u64 time,
                  unsigned int next_freq)
{
    if (sugov_update_next_freq(sg_policy, time, next_freq))
    //調(diào)用 cpufreq_driver_fast_switch,通過硬件驅(qū)動直接設(shè)置 CPU 頻率為 next_freq。
        cpufreq_driver_fast_switch(sg_policy->policy, next_freq);
}

sugov_deferred_update

//用于在不支持快速頻率切換(fast switch)的硬件上異步更新 CPU 頻率。
static void sugov_deferred_update(struct sugov_policy *sg_policy, u64 time,
unsigned int next_freq)
{
//如果 sugov_update_next_freq 返回 false(頻率未變且無需強(qiáng)制更新),直接退出函數(shù),避免不必要的異步處理。
//如果返回 true(頻率需要更新),繼續(xù)執(zhí)行后續(xù)邏輯。
if (!sugov_update_next_freq(sg_policy, time, next_freq))
return;
//檢查 work_in_progress 標(biāo)志(sugov_policy 字段),表示是否有頻率調(diào)整工作正在進(jìn)行。
//如果 work_in_progress 為 false(無工作進(jìn)行)
//設(shè)置 work_in_progress = true,標(biāo)記工作開始,防止重復(fù)調(diào)度。
if (!sg_policy->work_in_progress) {
sg_policy->work_in_progress = true;
//調(diào)用 irq_work_queue(&sg_policy->irq_work),將 sg_policy->irq_work 加入中斷工作隊(duì)列,異步觸發(fā)頻率調(diào)整。
irq_work_queue(&sg_policy->irq_work);
}
}

get_next_freq

//get_next_freq 是 schedutil 調(diào)度器的核心函數(shù),根據(jù) CPU 利用率(util)和容量(max)計(jì)算目標(biāo)頻率。
static unsigned int get_next_freq(struct sugov_policy *sg_policy,
unsigned long util, unsigned long max)
{
//獲取 sg_policy 中的 cpufreq_policy,包含頻率策略信息(如最大頻率 cpuinfo.max_freq、當(dāng)前頻率 cur、最小/最大限制)。
struct cpufreq_policy *policy = sg_policy->policy;
//根據(jù)硬件是否支持頻率不變(frequency-invariant)選擇基準(zhǔn)頻率:
//如果支持(arch_scale_freq_invariant() 返回 true),使用最大頻率 cpuinfo.max_freq。
//否則,使用當(dāng)前頻率 policy->cur。
//頻率不變意味著利用率已標(biāo)準(zhǔn)化,基于最大頻率計(jì)算;否則,需根據(jù)當(dāng)前頻率調(diào)整。
unsigned int freq = arch_scale_freq_invariant() ?
policy->cpuinfo.max_freq : policy->cur;
unsigned long next_freq = 0;
//調(diào)用 Android 特定的跟蹤鉤子(vendor hook),允許外部模塊(如 Android 廠商驅(qū)動)修改頻率計(jì)算。
//參數(shù)包括 util、基準(zhǔn) freq、最大容量 max,輸出到 next_freq 和 need_freq_update。
//這是一個(gè)擴(kuò)展點(diǎn),常用于 Android 設(shè)備優(yōu)化頻率選擇。
trace_android_vh_map_util_freq(util, freq, max, &next_freq, policy,
&sg_policy->need_freq_update);
//如果 next_freq 非 0(外部鉤子提供了頻率),使用 next_freq。
if (next_freq)
freq = next_freq;
else
//否則,調(diào)用 map_util_freq 計(jì)算頻率:
//對于頻率不變:next_freq = 1.25 * max_freq * util / max(注釋中的公式,C=1.25,tipping point 為 util/max=0.8)。
//對于非頻率不變:next_freq = 1.25 * curr_freq * util / max。
//系數(shù) 1.25 放大利用率,確保在 80% 利用率時(shí)達(dá)到最大頻率。
freq = map_util_freq(util, freq, max);
//檢查計(jì)算出的 freq 是否與緩存的 cached_raw_freq 相同,且無需強(qiáng)制更新(need_freq_update 為 false)。
//如果是,返回當(dāng)前 next_freq,避免重復(fù)計(jì)算和驅(qū)動調(diào)用,優(yōu)化性能。
if (freq == sg_policy->cached_raw_freq && !sg_policy->need_freq_update)
return sg_policy->next_freq;
//更新 cached_raw_freq,緩存本次計(jì)算的原始頻率,用于下次比較。
sg_policy->cached_raw_freq = freq;
//調(diào)用 cpufreq_driver_resolve_freq,將計(jì)算的 freq 轉(zhuǎn)換為驅(qū)動支持的最接近頻率(不低于 freq),并確保在策略的 min 和 max 范圍內(nèi)。
//返回最終的頻率值(kHz)。
return cpufreq_driver_resolve_freq(policy, freq);
}

schedutil_cpu_util

//cpu:目標(biāo) CPU 的編號。
//util_cfs:CFS(Completely Fair Scheduler)任務(wù)的利用率。
//max:CPU 的最大容量(通常為 SCHED_CAPACITY_SCALE,即 1024)。
//type:利用率類型,FREQUENCY_UTIL(頻率選擇)或 ENERGY_UTIL(能耗計(jì)算)。
//p:指向任務(wù)結(jié)構(gòu)體(task_struct),用于利用率鉗制(uclamp)。
unsigned long schedutil_cpu_util(int cpu, unsigned long util_cfs,
unsigned long max, enum schedutil_type type,
struct task_struct *p)
{
unsigned long dl_util, util, irq;
//獲取 CPU 的運(yùn)行隊(duì)列(rq)。
struct rq *rq = cpu_rq(cpu);
//如果未啟用利用率鉗制(uclamp)、類型為 FREQUENCY_UTIL 且 RT(實(shí)時(shí))任務(wù)可運(yùn)行,直接返回最大容量(max)
//這是因?yàn)?RT 任務(wù)優(yōu)先級高,需以最大頻率運(yùn)行。
if (!uclamp_is_used() &&
type == FREQUENCY_UTIL && rt_rq_is_runnable(&rq->rt)) {
return max;
}

//獲取 IRQ/steal 時(shí)間利用率(irq)。
//如果 IRQ 利用率飽和(irq >= max),返回最大容量,表示 CPU 被中斷或 steal 時(shí)間占滿,需最高頻率。

irq = cpu_util_irq(rq);
if (unlikely(irq >= max))
    return max;

//將 CFS 利用率(util_cfs)和 RT 利用率(cpu_util_rt)相加。
//如果是頻率選擇(FREQUENCY_UTIL),應(yīng)用利用率鉗制(uclamp),根據(jù)任務(wù) p 的約束調(diào)整 util(如限制最大/最小頻率)。
util = util_cfs + cpu_util_rt(rq);
if (type == FREQUENCY_UTIL)
util = uclamp_rq_util_with(rq, util, p);

//獲取 DL(deadline)任務(wù)的利用率(cpu_util_dl)。
//如果 CFS+RT+DL 利用率之和飽和(>= max),返回最大容量,表示無空閑時(shí)間,需最高頻率。

dl_util = cpu_util_dl(rq);

if (util + dl_util >= max)
    return max;

//如果是能耗計(jì)算(ENERGY_UTIL),將 DL 利用率加入 util,以估算實(shí)際運(yùn)行時(shí)間(包括 DL 任務(wù))。
if (type == ENERGY_UTIL)
util += dl_util;

/*
 * There is still idle time; further improve the number by using the
 * irq metric. Because IRQ/steal time is hidden from the task clock we
 * need to scale the task numbers:
 *
 *              max - irq
 *   U' = irq + --------- * U
 *                 max
 */

//使用公式 U' = irq + (max - irq) / max * U 縮放 util,補(bǔ)償 IRQ/steal 時(shí)間對任務(wù)時(shí)鐘的隱藏影響。
//然后加上 irq,得到更準(zhǔn)確的利用率。
util = scale_irq_capacity(util, irq, max);
util += irq;

/*
 * Bandwidth required by DEADLINE must always be granted while, for
 * FAIR and RT, we use blocked utilization of IDLE CPUs as a mechanism
 * to gracefully reduce the frequency when no tasks show up for longer
 * periods of time.
 *
 * Ideally we would like to set bw_dl as min/guaranteed freq and util +
 * bw_dl as requested freq. However, cpufreq is not yet ready for such
 * an interface. So, we only do the latter for now.
 */
 如果是頻率選擇,將 DL 任務(wù)的帶寬需求(cpu_bw_dl)加入 util,確保滿足 deadline 任務(wù)的最小頻率要求。
if (type == FREQUENCY_UTIL)
    util += cpu_bw_dl(rq);

//返回 util 和 max 的最小值,確保利用率不超過最大容量。
return min(max, util);
}

EXPORT_SYMBOL_GPL

EXPORT_SYMBOL_GPL:
這是一個(gè) Linux 內(nèi)核宏,用于將指定的函數(shù)或變量符號(這里是 schedutil_cpu_util)導(dǎo)出到內(nèi)核符號表。

導(dǎo)出的符號可以被其他內(nèi)核模塊(動態(tài)加載的模塊)訪問和調(diào)用。

GPL 后綴表示該符號僅限于 GPL 許可的模塊使用,限制非 GPL 模塊訪問,遵循 Linux 內(nèi)核的許可要求。

schedutil_cpu_util:
如您之前提供的代碼,schedutil_cpu_util 是一個(gè)函數(shù),計(jì)算 CPU 的有效利用率(基于 CFS、RT、DL 任務(wù)、IRQ 時(shí)間和 DL 帶寬),用于頻率選擇(FREQUENCY_UTIL)或能耗計(jì)算(ENERGY_UTIL)。

它的輸出(利用率)被 get_next_freq 使用,影響 CPU 頻率調(diào)整。

作用:
通過 EXPORT_SYMBOL_GPL,schedutil_cpu_util 函數(shù)對其他 GPL 許可的內(nèi)核模塊開放,例如:
其他頻率調(diào)節(jié)器模塊,可能需要 CPU 利用率數(shù)據(jù)。

能耗管理模塊(如 Energy Aware Scheduling, EAS),用于優(yōu)化調(diào)度決策。

廠商定制模塊(如 Android 的電源管理擴(kuò)展)。

這提高了內(nèi)核模塊的復(fù)用性和擴(kuò)展性,允許外部模塊利用 schedutil 的利用率計(jì)算邏輯。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容