偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

聊聊 Linux 分配 CPU 資源的第二種能力,對各個(gè)容器按照權(quán)重進(jìn)行分配!

系統(tǒng) Linux
Linux 內(nèi)核中的完全公平調(diào)度器中每個(gè)邏輯核都有一個(gè)調(diào)度隊(duì)列 struct cfs_rq。每個(gè)調(diào)度隊(duì)列中都是用紅黑樹來組織的。紅黑樹的節(jié)點(diǎn)是 struct sched_entity, sched_entity 中既可以關(guān)聯(lián)具體的進(jìn)程 struct task_struct 也可以關(guān)聯(lián)容器的 struct cfs_rq。

這篇文章中我們介紹了Linux內(nèi)核給容器分配CPU資源的第一種方式,通過 period 和 quota 的組合來限制容器使用的CPU時(shí)間上限。但其實(shí)內(nèi)核給實(shí)現(xiàn)CPU資源分配還存在第二種方式,那就是按權(quán)重分配。我們來看看這種分配方式是如何使用的,底層實(shí)現(xiàn)原理又是怎樣的。

一、Linux的完全公平調(diào)度器

在講容器權(quán)重分配之前,我們得先來回顧一下內(nèi)核的完全公平調(diào)度器的實(shí)現(xiàn)。

Linux 內(nèi)核中的完全公平調(diào)度器中每個(gè)邏輯核都有一個(gè)調(diào)度隊(duì)列 struct cfs_rq。每個(gè)調(diào)度隊(duì)列中都是用紅黑樹來組織的。紅黑樹的節(jié)點(diǎn)是 struct sched_entity, sched_entity 中既可以關(guān)聯(lián)具體的進(jìn)程 struct task_struct 也可以關(guān)聯(lián)容器的 struct cfs_rq。

圖片圖片

以下是完全公平調(diào)度器 cfs_rq 內(nèi)核對象的定義。

// file:kernel/sched/sched.h
struct cfs_rq {
 ...
 // 當(dāng)前隊(duì)列中所有進(jìn)程vruntime中的最小值  
 u64 min_vruntime;
 // 保存就緒任務(wù)的紅黑樹
 struct rb_root_cached tasks_timeline;
 ...
}

在該對象中,最核心的是這個(gè) rb_root_cached 類型的對象,這個(gè)對象的數(shù)據(jù)結(jié)構(gòu)就是以紅黑樹來組織的。在紅黑樹的節(jié)點(diǎn)中,放是一個(gè)調(diào)度實(shí)體 sched_entity 對象。這個(gè)對象有可能是屬于普通進(jìn)程 task_struct 的,也有可能是屬于容器進(jìn)程組 task_group。

//file:kernel/sched/sched.h
struct task_group {
 ...
 struct sched_entity **se;
 struct cfs_rq  **cfs_rq;
 unsigned long  shares;
}
//file:include/linux/sched.h
struct task_struct {
 ...
 struct sched_entity  se;
}

不管 sched_entity 是對應(yīng)的進(jìn)程也好,還是容器也罷,都會(huì)包含一個(gè)虛擬運(yùn)行時(shí)間 vruntime 字段,和一個(gè)用來存權(quán)重?cái)?shù)據(jù)的 load 字段。

圖片圖片

在進(jìn)程調(diào)度的過程中,每個(gè)邏輯核上有一個(gè)定時(shí)器,節(jié)拍性地觸發(fā)調(diào)度從紅黑樹上判斷是否要用最左側(cè)調(diào)度實(shí)體替換調(diào)當(dāng)前正在運(yùn)行的進(jìn)程。在選擇進(jìn)程進(jìn)行切換時(shí),雖然都多種策略,但最核心的是要保持所有調(diào)度實(shí)體的 vruntime 的公平。換句話說,不管 Linux 系統(tǒng)上有多少個(gè)使用完全公平調(diào)度器的進(jìn)程(使用實(shí)時(shí)調(diào)度策略的進(jìn)程除外),他們最終的 vruntime 基本會(huì)保持一致。

二、權(quán)重的設(shè)置

上節(jié)我們講到完全公平調(diào)度器運(yùn)轉(zhuǎn)是基于 vruntime 的來維持所有調(diào)度實(shí)體公平地使用 CPU 資源的。但現(xiàn)實(shí)情況是,有的服務(wù)確實(shí)是需要多使用一些CPU 資源,另一些服務(wù)只需要少使用一點(diǎn)就可以。例如說某臺(tái)服務(wù)機(jī)是云上的一臺(tái)服務(wù)器,有的用戶購買了 8 核套餐,有的用戶只購買的 1 核。在計(jì)算 vruntime 的時(shí)候必然需要一些策略。

為了實(shí)現(xiàn)這個(gè)需求,每個(gè)調(diào)度實(shí)體中的都有一個(gè)權(quán)重就非常地有用了。

//file:include/linux/sched.h
struct sched_entity {
 struct load_weight  load;
 u64    vruntime;
 ...
}

struct load_weight {
 unsigned long weight;
 u32    inv_weight;
};

對于普通進(jìn)程來說,這個(gè)權(quán)重可以使用 nice 命令來間接地修改。在容器中,在 cgroup v1 下可以通過 cgroupfs 下的 cpu.shares 文件來修改,在cgroup v2 下通過 cpu.weight / cpu.weight.nice 來修改。

在 cgroup v1 中,對 cpu.shares 的修改會(huì)執(zhí)行到 cpu_shares_write_u64 這個(gè)函數(shù)中。

//file:kernel/sched/core.c
static struct cftype cpu_legacy_files[] = {
 {
  .name = "shares",
  .read_u64 = cpu_shares_read_u64,
  .write_u64 = cpu_shares_write_u64,
 },
 ...
}

在 cgroup v2 中,對 cpu.weight 的修改會(huì)執(zhí)行到 cpu_weight_write_u64 函數(shù)中。

//file:kernel/sched/core.c
static struct cftype cpu_files[] = {
 {
  .name = "weight",
  .flags = CFTYPE_NOT_ON_ROOT,
  .read_u64 = cpu_weight_read_u64,
  .write_u64 = cpu_weight_write_u64,
 },
 ...
}

不管是 cgroup v1 修改 cpu.shares 時(shí)執(zhí)行 cpu_shares_write_u64,還是 cgroup v2 修改 cpu.weight 是執(zhí)行 cpu_weight_write_u64,最終都會(huì)調(diào)用到 __sched_group_set_shares 來把權(quán)重信息 shares 記錄到調(diào)度實(shí)體  se 上去的。

//file:kernel/sched/fair.c
static int __sched_group_set_shares(struct task_group *tg, unsigned long shares)
{
 ......
 tg->shares = shares;
 for_each_possible_cpu(i) {
  struct sched_entity *se = tg->se[i];
  for_each_sched_entity(se) 
   update_cfs_group(se);
  }
 }
}

具體的設(shè)置是在 update_cfs_group 中完成的,它依次調(diào)用 reweight_entity、update_load_set 來把權(quán)重值記錄到調(diào)度實(shí)體上。這樣后面就可以通過調(diào)度實(shí)體 se->load->weight 找到進(jìn)程或容器的權(quán)重信息了。

//file:kernel/sched/fair.c
static inline void update_load_set(struct load_weight *lw, unsigned long w)
{
 lw->weight = w;
 lw->inv_weight = 0;
}

三、容器 CPU 權(quán)重分配實(shí)現(xiàn)

完全公平調(diào)度器是維持的所有調(diào)度實(shí)體的 vruntime 的公平。但是 vruntime 會(huì)根據(jù)權(quán)重來進(jìn)行縮放,vruntime 的實(shí)現(xiàn)是 calc_delta_fair 函數(shù)。

// file:kernel/sched/fair.c
static inline u64 calc_delta_fair(u64 delta, struct sched_entity *se)
{
 if (unlikely(se->load.weight != NICE_0_LOAD))
  delta = __calc_delta(delta, NICE_0_LOAD, &se->load);

 return delta;
}

在這個(gè)函數(shù)中,NICE_0_LOAD 宏對應(yīng)的是 1024。如果權(quán)重是 1024,那么 vruntime 就正好等于實(shí)際運(yùn)行時(shí)間。否則會(huì)進(jìn)入到 __calc_delta 中來根據(jù)權(quán)重和實(shí)際運(yùn)行時(shí)間來折算一個(gè) vruntime 增量來。__calc_delta 函數(shù)為了追求極致的性能,實(shí)現(xiàn)上比較復(fù)雜一些,源碼就不給大家展示了。我們只把它用到的縮放算法展示如下:

vruntime = (實(shí)際運(yùn)行時(shí)間 * ((NICE_0_LOAD * 2^32) / weight)) >> 32

如果權(quán)重 weight 較高,那同樣的實(shí)際運(yùn)行時(shí)間算出來的 vruntime 就會(huì)偏小,這樣它就會(huì)在調(diào)度中獲得更多的 CPU。如果權(quán)重 weight 較低,那算出來的 vruntime 就會(huì)比實(shí)際運(yùn)行時(shí)間偏大。這樣它就會(huì)在調(diào)度的過程中獲得的 CPU 時(shí)間就會(huì)較少。完全公平調(diào)度器就是這樣簡單地實(shí)現(xiàn)了 CPU 資源的按權(quán)重分配。

我們再舉個(gè)例子,假如有一個(gè) 8 核的物理上,上面運(yùn)行著 A 服務(wù)、B 服務(wù)、C 服務(wù)的一些容器。

圖片圖片

責(zé)任編輯:武曉燕 來源: 開發(fā)內(nèi)功修煉
相關(guān)推薦

2021-03-30 09:21:09

PythonSeleniumPython爬蟲

2025-09-08 02:00:00

2021-12-16 06:52:33

C語言內(nèi)存分配

2009-12-24 11:04:59

固定分配資源動(dòng)態(tài)分配資源

2022-02-11 09:31:23

IPV4IP地址IANA

2023-10-24 07:25:10

容器資源云分級

2022-11-30 08:19:15

內(nèi)存分配Go逃逸分析

2021-08-31 23:09:27

Spark資源分配

2009-06-18 15:41:36

動(dòng)態(tài)分配CPUJava

2022-12-12 08:42:06

Java對象棧內(nèi)存

2023-10-17 00:01:34

Linux操作系統(tǒng)

2021-03-05 00:06:12

Docker容器內(nèi)存

2009-10-23 17:35:16

linux進(jìn)程管理

2010-04-07 15:55:17

無線接入頻段

2014-12-26 10:58:35

托管云托管私有云公共云

2015-04-17 10:28:02

無線頻譜移動(dòng)通信頻譜

2011-05-18 10:42:48

2011-04-19 13:48:55

vCloud Dire

2011-04-19 13:32:52

2024-01-01 18:59:15

KubernetesCPU內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號