女人荫蒂被添全过程13种图片,亚洲+欧美+在线,欧洲精品无码一区二区三区 ,在厨房拨开内裤进入毛片

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Linux是如何對(duì)容器下的進(jìn)程進(jìn)行CPU限制的,底層是如何工作的?

dyquk4xk2p3d ? 來(lái)源:開(kāi)發(fā)內(nèi)功修煉 ? 2023-11-29 14:31 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

現(xiàn)在很多公司的服務(wù)都是跑在容器下,我來(lái)問(wèn)幾個(gè)容器 CPU 相關(guān)的問(wèn)題,看大家對(duì)天天在用的技術(shù)是否熟悉。

容器中的核是真的邏輯核嗎?

Linux 是如何對(duì)容器下的進(jìn)程進(jìn)行 CPU 限制的,底層是如何工作的?

容器中的 throttle 是什么意思?

為什么關(guān)注容器 CPU 性能的時(shí)候,除了關(guān)注使用率,還要關(guān)注 throttle 的次數(shù)和時(shí)間?

和真正使用物理機(jī)不同,Linux 容器中所謂的核并不是真正的 CPU 核。所以在理解容器 CPU 性能的時(shí)候,必然要有一些特殊的地方需要考慮。

各家公司的容器云上,底層不管使用的是 docker 引擎,還是 containerd 引擎,都是依賴 Linux 的 cgroup 的 cpu 子系統(tǒng)來(lái)工作的,所以今天我們就來(lái)深入地學(xué)習(xí)一下 cgroup cpu 子系統(tǒng) 。理解了這個(gè),你將會(huì)對(duì)容器進(jìn)程的 CPU 性能有更深入的把握。

一、cgroup 的 cpu 子系統(tǒng)

在 Linux 下, cgroup 提供了對(duì) CPU、內(nèi)存等資源實(shí)現(xiàn)精細(xì)化控制的能力。它的全稱是 control groups。允許對(duì)某一個(gè)進(jìn)程,或者一組進(jìn)程所用到的資源進(jìn)行控制。現(xiàn)在流行的 Docker 就是在這個(gè)底層機(jī)制上成長(zhǎng)起來(lái)的。

在你的機(jī)器執(zhí)行執(zhí)行下面的命令可以查看當(dāng)前 cgroup 都支持對(duì)哪些資源進(jìn)行控制。

$lssubsys-a
cpuset
cpu,cpuacct
...

其中 cpu 和 cpuset 都是對(duì) CPU 資源進(jìn)行控制的子系統(tǒng)。cpu 是通過(guò)執(zhí)行時(shí)間來(lái)控制進(jìn)程對(duì) cpu 的使用,cpuset 是通過(guò)分配邏輯核的方式來(lái)分配 cpu。其它可控制的資源還包括 memory(內(nèi)存)、net_cls(網(wǎng)絡(luò)帶寬)等等。

cgroup 提供了一個(gè)原生接口并通過(guò) cgroupfs 提供控制。類似于 procfs 和 sysfs,是一種虛擬文件系統(tǒng)。默認(rèn)情況下 cgroupfs 掛載在 /sys/fs/cgroup 目錄下,我們可以通過(guò)修改 /sys/fs/cgroup 下的文件和文件內(nèi)容來(lái)控制進(jìn)程對(duì)資源的使用。

比如,想實(shí)現(xiàn)讓某個(gè)進(jìn)程只使用兩個(gè)核,我們可以通過(guò) cgroupfs 接口這樣來(lái)實(shí)現(xiàn),如下:

#cd/sys/fs/cgroup/cpu,cpuacct
#mkdirtest
#cdtest
#echo100000>cpu.cfs_period_us//100ms
#echo100000>cpu.cfs_quota_us//200ms
#echo{$pid}>cgroup.procs

其中 cfs_period_us 用來(lái)配置時(shí)間周期長(zhǎng)度,cfs_quota_us 用來(lái)配置當(dāng)前 cgroup 在設(shè)置的周期長(zhǎng)度內(nèi)所能使用的 CPU 時(shí)間。這兩個(gè)文件配合起來(lái)就可以設(shè)置 CPU 的使用上限。

上面的配置就是設(shè)置改 cgroup 下的進(jìn)程每 100 ms 內(nèi)只能使用 200 ms 的 CPU 周期,也就是說(shuō)限制使用最多兩個(gè)“核”。

要注意的是這種方式只限制的是 CPU 使用時(shí)間,具體調(diào)度的時(shí)候是可能會(huì)調(diào)度到任意 CPU 上執(zhí)行的。如果想限制進(jìn)程使用的 CPU 核,可以使用 cpuset 子系統(tǒng)。

docker 默認(rèn)情況下使用的就是 cgroupfs 接口,可以通過(guò)如下的命令來(lái)確認(rèn)。

#dockerinfo|grepcgroup
CgroupDriver:cgroupfs

二、內(nèi)核中進(jìn)程和 cgroup 的關(guān)系

在上一節(jié)中,我們?cè)?/sys/fs/cgroup/cpu,cpuacct 創(chuàng)建了一個(gè)目錄 test,這其實(shí)是創(chuàng)建了一個(gè) cgroup 對(duì)象。當(dāng)我們把某個(gè)進(jìn)程的 pid 添加到 cgroup 后,又是建立了進(jìn)程結(jié)構(gòu)體和 cgroup 之間的關(guān)系。

所以要想理解清 cgroup 的工作過(guò)程,就得先來(lái)了解一下 cgroup 和 task_struct 結(jié)構(gòu)體之間的關(guān)系。

2.1 cgroup 內(nèi)核對(duì)象

一個(gè) cgroup 對(duì)象中可以指定對(duì) cpu、cpuset、memory 等一種或多種資源的限制。我們先來(lái)找到 cgroup 的定義。

//file:include/linux/cgroup-defs.h
structcgroup{
...
structcgroup_subsys_state__rcu*subsys[CGROUP_SUBSYS_COUNT];
...
}

每個(gè) cgroup 都有一個(gè) cgroup_subsys_state 類型的數(shù)組 subsys,其中的每一個(gè)元素代表的是一種資源控制,如 cpu、cpuset、memory 等等。

76ae7904-8e7f-11ee-939d-92fbcf53809c.png

這里要注意的是,其實(shí) cgroup_subsys_state 并不是真實(shí)的資源控制統(tǒng)計(jì)信息結(jié)構(gòu),對(duì)于 CPU 子系統(tǒng)真正的資源控制結(jié)構(gòu)是 task_group。它是 cgroup_subsys_state 結(jié)構(gòu)的擴(kuò)展,類似父類和子類的概念。

76cb2f72-8e7f-11ee-939d-92fbcf53809c.png

當(dāng) task_group 需要被當(dāng)成 cgroup_subsys_state 類型使用的時(shí)候,只需要強(qiáng)制類型轉(zhuǎn)換就可以。

對(duì)于內(nèi)存子系統(tǒng)控制統(tǒng)計(jì)信息結(jié)構(gòu)是 mem_cgroup,其它子系統(tǒng)也類似。

76e616d4-8e7f-11ee-939d-92fbcf53809c.png

之所以要這么設(shè)計(jì),目的是各個(gè) cgroup 子系統(tǒng)都統(tǒng)一對(duì)外暴露 cgroup_subsys_state,其余部分不對(duì)外暴露,在自己的子系統(tǒng)內(nèi)部維護(hù)和使用。

2.2 進(jìn)程和 cgroup 子系統(tǒng)

一個(gè) Linux 進(jìn)程既可以對(duì)它的 cpu 使用進(jìn)行限制,也可以對(duì)它的內(nèi)存進(jìn)行限制。所以,一個(gè)進(jìn)程 task_struct 是可以和多種子系統(tǒng)有關(guān)聯(lián)關(guān)系的。

和 cgroup 和多個(gè)子系統(tǒng)關(guān)聯(lián)定義類似,task_struct 中也定義了一個(gè) cgroup_subsys_state 類型的數(shù)組 subsys,來(lái)表達(dá)這種一對(duì)多的關(guān)系。

771f190c-8e7f-11ee-939d-92fbcf53809c.png

我們來(lái)簡(jiǎn)單看下源碼的定義。

//file:include/linux/sched.h
structtask_struct{
...
structcss_set__rcu*cgroups;
...
}
//file:include/linux/cgroup-defs.h
structcss_set{
...
structcgroup_subsys_state*subsys[CGROUP_SUBSYS_COUNT];
}

其中subsys是一個(gè)指針數(shù)組,存儲(chǔ)一組指向 cgroup_subsys_state 的指針。一個(gè) cgroup_subsys_state 就是進(jìn)程與一個(gè)特定的子系統(tǒng)相關(guān)的信息。

通過(guò)這個(gè)指針,進(jìn)程就可以獲得相關(guān)聯(lián)的 cgroups 控制信息了。能查到限制該進(jìn)程對(duì)資源使用的 task_group、cpuset、mem_group 等子系統(tǒng)對(duì)象。

2.3 內(nèi)核對(duì)象關(guān)系圖匯總

我們把上面的內(nèi)核對(duì)象關(guān)系圖匯總起來(lái)看一下。

7743f7d6-8e7f-11ee-939d-92fbcf53809c.png

可以看到無(wú)論是進(jìn)程、還是 cgroup 對(duì)象,最后都能找到和其關(guān)聯(lián)的具體的 cpu、內(nèi)存等資源控制自系統(tǒng)的對(duì)象。

2.4 cpu 子系統(tǒng)

因?yàn)榻裉煳覀冎攸c(diǎn)是介紹進(jìn)程的 cpu 限制,所以我們把 cpu 子系統(tǒng)相關(guān)的對(duì)象 task_group 專門拿出來(lái)理解理解。

//file:kernel/sched/sched.h
structtask_group{
structcgroup_subsys_statecss;
...

//task_group樹(shù)結(jié)構(gòu)
structtask_group*parent;
structlist_headsiblings;
structlist_headchildren;

//task_group持有的N個(gè)調(diào)度實(shí)體(N=CPU核數(shù))
structsched_entity**se;

//task_group自己的N個(gè)公平調(diào)度隊(duì)列(N=CPU核數(shù))
structcfs_rq**cfs_rq;

//公平調(diào)度帶寬限制
structcfs_bandwidthcfs_bandwidth;
...
}

第一個(gè) cgroup_subsys_state css 成員我們?cè)谇懊嬲f(shuō)過(guò)了,這相當(dāng)于它的“父類”。再來(lái)看 parent、siblings、children 等幾個(gè)對(duì)象。這些成員是樹(shù)相關(guān)的數(shù)據(jù)結(jié)構(gòu)。在整個(gè)系統(tǒng)中有一個(gè) root_task_group。

//file:kernel/sched/core.c
structtask_grouproot_task_group;

所有的 task_group 都是以 root_task_group 為根節(jié)點(diǎn)組成了一棵樹(shù)。

接下來(lái)的 se 和 cfs_rq 是完全公平調(diào)度的兩個(gè)對(duì)象。它們兩都是數(shù)組,元素個(gè)數(shù)等于當(dāng)前系統(tǒng)的 CPU 核數(shù)。每個(gè) task_group 都會(huì)在上一級(jí) task_group(比如 root_task_group)的 N 個(gè)調(diào)度隊(duì)列中有一個(gè)調(diào)度實(shí)體。

cfs_rq 是 task_group 自己所持有的完全公平調(diào)度隊(duì)列。是的,你沒(méi)看錯(cuò)。每一個(gè) task_group 內(nèi)部都有自己的一組調(diào)度隊(duì)列,其數(shù)量和 CPU 的核數(shù)一致。

假如當(dāng)前系統(tǒng)有兩個(gè)邏輯核,那么一個(gè) task_group 樹(shù)和 cfs_rq 的簡(jiǎn)單示意圖大概是下面這個(gè)樣子。

775b0a20-8e7f-11ee-939d-92fbcf53809c.png

Linux 中的進(jìn)程調(diào)度是一個(gè)層級(jí)的結(jié)構(gòu)。對(duì)于容器來(lái)講,宿主機(jī)中進(jìn)行進(jìn)程調(diào)度的時(shí)候,先調(diào)度到的實(shí)際上不是容器中的具體某個(gè)進(jìn)程,而是一個(gè) task_group。然后接下來(lái)再進(jìn)入容器 task_group 的調(diào)度隊(duì)列 cfs_rq 中進(jìn)行調(diào)度,才能最終確定具體的進(jìn)程 pid。

還有就是 cpu 帶寬限制 cfs_bandwidth, cpu 分配的管控相關(guān)的字段都是在 cfs_bandwidth 中定義維護(hù)的。

cgroup 相關(guān)的內(nèi)核對(duì)象我們就先介紹到這里,接下來(lái)我們看一下 cpu 子系統(tǒng)到底是如何實(shí)現(xiàn)的。

三、CPU 子系統(tǒng)的實(shí)現(xiàn)

在第一節(jié)中我們展示通過(guò) cgroupfs 對(duì) cpu 子系統(tǒng)使用,使用過(guò)程大概可以分成三步:

第一步:通過(guò)創(chuàng)建目錄來(lái)創(chuàng)建 cgroup

第二步:在目錄中設(shè)置 cpu 的限制情況

第三步:將進(jìn)程添加到 cgroup 中進(jìn)行資源管控

那本小節(jié)我們就從上面三步展開(kāi),看看在每一步中,內(nèi)核都具體做了哪些事情。限于篇幅所限,我們只講 cpu 子系統(tǒng),對(duì)于其他的子系統(tǒng)也是類似的分析過(guò)程。

3.1 創(chuàng)建 cgroup 對(duì)象

內(nèi)核定義了對(duì) cgroupfs 操作的具體處理函數(shù)。在 /sys/fs/cgroup/ 下的目錄創(chuàng)建操作都將由下面 cgroup_kf_syscall_ops 定義的方法來(lái)執(zhí)行。

//file:kernel/cgroup/cgroup.c
staticstructkernfs_syscall_opscgroup_kf_syscall_ops={
.mkdir=cgroup_mkdir,
.rmdir=cgroup_rmdir,
...
};

創(chuàng)建目錄執(zhí)行整個(gè)過(guò)程鏈條如下

vfs_mkdir
->kernfs_iop_mkdir
->cgroup_mkdir
->cgroup_apply_control_enable
->css_create
->cpu_cgroup_css_alloc

其中關(guān)鍵的創(chuàng)建過(guò)程有:

cgroup_mkdir:在這里創(chuàng)建了 cgroup 內(nèi)核對(duì)象

css_create:創(chuàng)建每一個(gè)子系統(tǒng)資源管理對(duì)象,對(duì)于 cpu 子系統(tǒng)會(huì)創(chuàng)建 task_group

cgroup 內(nèi)核對(duì)象是在 cgroup_mkdir 中創(chuàng)建的。除了 cgroup 內(nèi)核對(duì)象,這里還創(chuàng)建了文件系統(tǒng)重要展示的目錄。

//file:kernel/cgroup/cgroup.c
intcgroup_mkdir(structkernfs_node*parent_kn,constchar*name,umode_tmode)
{
...
//查找父cgroup
parent=cgroup_kn_lock_live(parent_kn,false);

//創(chuàng)建cgroup對(duì)象出來(lái)
cgrp=cgroup_create(parent);

//創(chuàng)建文件系統(tǒng)節(jié)點(diǎn)
kn=kernfs_create_dir(parent->kn,name,mode,cgrp);
cgrp->kn=kn;
...
}

在 cgroup 中,是有層次的概念的,這個(gè)層次結(jié)構(gòu)和 cgroupfs 中的目錄層次結(jié)構(gòu)一樣。所以在創(chuàng)建 cgroup 對(duì)象之前的第一步就是先找到其父 cgroup, 然后創(chuàng)建自己,并創(chuàng)建文件系統(tǒng)中的目錄以及文件。

在 cgroup_apply_control_enable 中,執(zhí)行子系統(tǒng)對(duì)象的創(chuàng)建。

//file:kernel/cgroup/cgroup.c
staticintcgroup_apply_control_enable(structcgroup*cgrp)
{
...
cgroup_for_each_live_descendant_pre(dsct,d_css,cgrp){
for_each_subsys(ss,ssid){
structcgroup_subsys_state*css=cgroup_css(dsct,ss);
css=css_create(dsct,ss);
...
}
}
return0;
}

通過(guò) for_each_subsys 遍歷每一種 cgroup 子系統(tǒng),并調(diào)用其 css_alloc 來(lái)創(chuàng)建相應(yīng)的對(duì)象。

//file:kernel/cgroup/cgroup.c
staticstructcgroup_subsys_state*css_create(structcgroup*cgrp,
structcgroup_subsys*ss)
{
css=ss->css_alloc(parent_css);
...
}

上面的 css_alloc 是一個(gè)函數(shù)指針,對(duì)于 cpu 子系統(tǒng)來(lái)說(shuō),它指向的是 cpu_cgroup_css_alloc。這個(gè)對(duì)應(yīng)關(guān)系在 kernel/sched/core.c 文件仲可以找到

//file:kernel/sched/core.c
structcgroup_subsyscpu_cgrp_subsys={
.css_alloc=cpu_cgroup_css_alloc,
.css_online=cpu_cgroup_css_online,
...
};

通過(guò) cpu_cgroup_css_alloc => sched_create_group 調(diào)用后,創(chuàng)建出了 cpu 子系統(tǒng)的內(nèi)核對(duì)象 task_group。

//file:kernel/sched/core.c
structtask_group*sched_create_group(structtask_group*parent)
{
structtask_group*tg;
tg=kmem_cache_alloc(task_group_cache,GFP_KERNEL|__GFP_ZERO);
...
}

3.2 設(shè)置 CPU 子系統(tǒng)限制

第一節(jié)中,我們通過(guò)對(duì) cpu 子系統(tǒng)目錄下的 cfs_period_us 和 cfs_quota_us 值的修改,來(lái)完成了 cgroup 中限制的設(shè)置。我們這個(gè)小節(jié)再看看看這個(gè)設(shè)置過(guò)程。

當(dāng)用戶讀寫(xiě)這兩個(gè)文件的時(shí)候,內(nèi)核中也定義了對(duì)應(yīng)的處理函數(shù)。

//file:kernel/sched/core.c
staticstructcftypecpu_legacy_files[]={
...
{
.name="cfs_quota_us",
.read_s64=cpu_cfs_quota_read_s64,
.write_s64=cpu_cfs_quota_write_s64,
},
{
.name="cfs_period_us",
.read_u64=cpu_cfs_period_read_u64,
.write_u64=cpu_cfs_period_write_u64,
},
...
}

寫(xiě)處理函數(shù) cpu_cfs_quota_write_s64、cpu_cfs_period_write_u64 最終又都是調(diào)用 tg_set_cfs_bandwidth 來(lái)完成設(shè)置的。

//file:kernel/sched/core.c
staticinttg_set_cfs_bandwidth(structtask_group*tg,u64period,u64quota)
{
//定位cfs_bandwidth對(duì)象
structcfs_bandwidth*cfs_b=&tg->cfs_bandwidth;
...

//對(duì)cfs_bandwidth進(jìn)行設(shè)置
cfs_b->period=ns_to_ktime(period);
cfs_b->quota=quota;
...
}

在 task_group 中,其帶寬管理控制都是由 cfs_bandwidth 來(lái)完成的,所以一開(kāi)始就需要先獲取 cfs_bandwidth 對(duì)象。接著將用戶設(shè)置的值都設(shè)置到 cfs_bandwidth 類型的對(duì)象 cfs_b 上。

3.3 寫(xiě) proc 進(jìn) group

cgroup 創(chuàng)建好了,cpu 限制規(guī)則也制定好了,下一步就是將進(jìn)程添加到這個(gè)限制中。在 cgroupfs 下的操作方式就是修改 cgroup.procs 文件。

內(nèi)核定義了修改 cgroup.procs 文件的處理函數(shù)為 cgroup_procs_write。

//file:kernel/cgroup/cgroup.c
staticstructcftypecgroup_base_files[]={
...
{
.name="cgroup.procs",
...
.write=cgroup_procs_write,
},
}

在 cgroup_procs_write 的處理中,主要做了這么幾件事情。

第一、邏根據(jù)用戶輸入的 pid 來(lái)查找 task_struct 內(nèi)核對(duì)象。

第二、從舊的調(diào)度組中退出,加入到新的調(diào)度組 task_group 中

第三、修改進(jìn)程其 cgroup 相關(guān)的指針,讓其指向上面創(chuàng)建好的 task_group。

我們來(lái)看下加入新調(diào)度組的過(guò)程,內(nèi)核的調(diào)用鏈條如下。

cgroup_procs_write
->cgroup_attach_task
->cgroup_migrate
->cgroup_migrate_execute

在 cgroup_migrate_execute 中遍歷各個(gè)子系統(tǒng),完成每一個(gè)子系統(tǒng)的遷移。

staticintcgroup_migrate_execute(structcgroup_mgctx*mgctx)
{
do_each_subsys_mask(ss,ssid,mgctx->ss_mask){
if(ss->attach){
tset->ssid=ssid;
ss->attach(tset);
}
}while_each_subsys_mask();
...
}

對(duì)于 cpu 子系統(tǒng)來(lái)講,attach 對(duì)應(yīng)的處理方法是 cpu_cgroup_attach。這也是在 kernel/sched/core.c 下的 cpu_cgrp_subsys 中定義的。

cpu_cgroup_attach 調(diào)用 sched_move_task 來(lái)完成將進(jìn)程加入到新調(diào)度組的過(guò)程。

//file:kernel/sched/core.c
voidsched_move_task(structtask_struct*tsk)
{
//找到task所在的runqueue
rq=task_rq_lock(tsk,&rf);

//從runqueue中出來(lái)
queued=task_on_rq_queued(tsk);
if(queued)
dequeue_task(rq,tsk,queue_flags);

//修改task的group
//將進(jìn)程先從舊tg的cfs_rq中移除且更新cfs_rq的負(fù)載;再將進(jìn)程添加入新tg的cfs_rq并更新新cfs_rq的負(fù)載
sched_change_group(tsk,TASK_MOVE_GROUP);

//此時(shí)進(jìn)程的調(diào)度組已經(jīng)更新,重新將進(jìn)程加回runqueue
if(queued)
enqueue_task(rq,tsk,queue_flags);
...
}

這個(gè)函數(shù)做了三件事。

第一、先調(diào)用 dequeue_task 從原歸屬的 queue 中退出來(lái),

第二、修改進(jìn)程的 task_group

第三、重新將進(jìn)程添加到新 task_group 的 runqueue 中。

//file:kernel/sched/core.c
staticvoidsched_change_group(structtask_struct*tsk,inttype)
{
structtask_group*tg;

//查找task_group
tg=container_of(task_css_check(tsk,cpu_cgrp_id,true),
structtask_group,css);
tg=autogroup_task_group(tsk,tg);

//修改task_struct所對(duì)應(yīng)的task_group
tsk->sched_task_group=tg;
...
}

進(jìn)程 task_struct 的 sched_task_group 是表示其歸屬的 task_group, 這里設(shè)置到新歸屬上。

四、進(jìn)程 CPU 帶寬控制過(guò)程

在前面的操作完畢之后,我們只是將進(jìn)程添加到了 cgroup 中進(jìn)行管理而已。相當(dāng)于只是初始化,而真正的限制是貫穿在 Linux 運(yùn)行是的進(jìn)程調(diào)度過(guò)程中的。

所添加的進(jìn)程將會(huì)受到 cpu 子系統(tǒng) task_group 下的 cfs_bandwidth 中記錄的 period 和 quota 的限制。

在你的新進(jìn)程是如何被內(nèi)核調(diào)度執(zhí)行到的?一文中我們介紹過(guò)完全公平調(diào)度器在選擇進(jìn)程時(shí)的核心方法 pick_next_task_fair。

這個(gè)方法的整個(gè)執(zhí)行過(guò)程一個(gè)自頂向下搜索可執(zhí)行的 task_struct 的過(guò)程。整個(gè)系統(tǒng)中有一個(gè) root_task_group。

//file:kernel/sched/core.c
structtask_grouproot_task_group;

775b0a20-8e7f-11ee-939d-92fbcf53809c.png

CFS 中調(diào)度隊(duì)列是一顆紅黑樹(shù), 紅黑樹(shù)的節(jié)點(diǎn)是 struct sched_entity, sched_entity 中既可以指向 struct task_struct 也可以指向 struct cfs_rq(可理解為 task_group)

調(diào)度 pick_next_task_fair()函數(shù)中的 prev 是本次調(diào)度時(shí)在執(zhí)行的上一個(gè)進(jìn)程。該函數(shù)通過(guò) do {} while 循環(huán),自頂向下搜索到下一步可執(zhí)行進(jìn)程。

//file:kernel/sched/fair.c
staticstructtask_struct*
pick_next_task_fair(structrq*rq,structtask_struct*prev,structrq_flags*rf)
{
structcfs_rq*cfs_rq=&rq->cfs;
...

//選擇下一個(gè)調(diào)度的進(jìn)程
do{
...
se=pick_next_entity(cfs_rq,curr);
cfs_rq=group_cfs_rq(se);
}while(cfs_rq)
p=task_of(se);

//如果選出的進(jìn)程和上一個(gè)進(jìn)程不同
if(prev!=p){
structsched_entity*pse=&prev->se;
...

//對(duì)要放棄CPU的進(jìn)程執(zhí)行一些處理
put_prev_entity(cfs_rq,pse);
}

}

如果新進(jìn)程和上一次運(yùn)行的進(jìn)程不是同一個(gè),則要調(diào)用 put_prev_entity 做兩件和 CPU 的帶寬控制有關(guān)的事情。

//file:kernel/sched/fair.c
staticvoidput_prev_entity(structcfs_rq*cfs_rq,structsched_entity*prev)
{
//4.1運(yùn)行隊(duì)列帶寬的更新與申請(qǐng)
if(prev->on_rq)
update_curr(cfs_rq);

//4.2判斷是否需要將容器掛起
check_cfs_rq_runtime(cfs_rq);

//更新負(fù)載數(shù)據(jù)
update_load_avg(cfs_rq,prev,0);
...
}

在上述代碼中,和 CPU 帶寬控制相關(guān)的操作有兩個(gè)。

運(yùn)行隊(duì)列帶寬的更新與申請(qǐng)

判斷是否需要進(jìn)行帶寬限制

接下來(lái)我們分兩個(gè)小節(jié)詳細(xì)展開(kāi)看看這兩個(gè)操作具體都做了哪些事情。

4.1 運(yùn)行隊(duì)列帶寬的更新與申請(qǐng)

在這個(gè)小節(jié)中我們專門來(lái)看看 cfs_rq 隊(duì)列中 runtime_remaining 的更新與申請(qǐng)

在實(shí)現(xiàn)上帶寬控制是在 task_group 下屬的 cfs_rq 隊(duì)列中進(jìn)行的。cfs_rq 對(duì)帶寬時(shí)間的操作歸總起來(lái)就是更新與申請(qǐng)。申請(qǐng)到的時(shí)間保存在字段 runtime_remaining 字段中,每當(dāng)有時(shí)間支出需要更新的時(shí)候也是從這個(gè)字段值從去除。

其實(shí)除了上述場(chǎng)景外,系統(tǒng)在很多情況下都會(huì)調(diào)用 update_curr,包括任務(wù)在入隊(duì)、出隊(duì)時(shí),調(diào)度中斷函數(shù)也會(huì)周期性地調(diào)用該方法,以確保任務(wù)的各種時(shí)間信息隨時(shí)都是最新的狀態(tài)。在這里會(huì)更新 cfs_rq 隊(duì)列中的 runtime_remaining 時(shí)間。如果 runtime_remaining 不足,會(huì)觸發(fā)時(shí)間申請(qǐng)。

//file:kernel/sched/fair.c
staticvoidupdate_curr(structcfs_rq*cfs_rq)
{
//計(jì)算一下運(yùn)行了多久
u64now=rq_clock_task(rq_of(cfs_rq));
u64delta_exec;
delta_exec=now-curr->exec_start;
...

//更新帶寬限制
account_cfs_rq_runtime(cfs_rq,delta_exec);
}

在 update_curr 先計(jì)算當(dāng)前執(zhí)行了多少時(shí)間。然后在 cfs_rq 的 runtime_remaining 減去該時(shí)間值,具體減的過(guò)程是在 account_cfs_rq_runtime 中處理的。

//file:kernel/sched/fair.c
staticvoid__account_cfs_rq_runtime(structcfs_rq*cfs_rq,u64delta_exec)
{
cfs_rq->runtime_remaining-=delta_exec;

//如果還有剩余時(shí)間,則函數(shù)返回
if(likely(cfs_rq->runtime_remaining>0))
return;
...
//調(diào)用assign_cfs_rq_runtime申請(qǐng)時(shí)間余額
if(!assign_cfs_rq_runtime(cfs_rq)&&likely(cfs_rq->curr))
resched_curr(rq_of(cfs_rq));
}

更新帶寬時(shí)間的邏輯比較簡(jiǎn)單,先從 cfs->runtime_remaining 減去本次執(zhí)行的物理時(shí)間。如果減去之后仍然大于 0 ,那么本次更新就算是結(jié)束了。

如果相減后發(fā)現(xiàn)是負(fù)數(shù),表示當(dāng)前 cfs_rq 的時(shí)間余額已經(jīng)耗盡,則會(huì)立即嘗試從任務(wù)組中申請(qǐng)。具體的申請(qǐng)函數(shù)是 assign_cfs_rq_runtime。如果申請(qǐng)沒(méi)能成功,調(diào)用 resched_curr 標(biāo)記 cfs_rq->curr 的 TIF_NEED_RESCHED 位,以便隨后將其調(diào)度出去。

我們展開(kāi)看下申請(qǐng)過(guò)程 assign_cfs_rq_runtime 。

//file:kernel/sched/fair.c
staticintassign_cfs_rq_runtime(structcfs_rq*cfs_rq)
{
//獲取當(dāng)前task_group的cfs_bandwidth
structtask_group*tg=cfs_rq->tg;
structcfs_bandwidth*cfs_b=tg_cfs_bandwidth(tg);

//申請(qǐng)時(shí)間數(shù)量為保持下次有sysctl_sched_cfs_bandwidth_slice這么多
min_amount=sched_cfs_bandwidth_slice()-cfs_rq->runtime_remaining;

//如果沒(méi)有限制,則要多少給多少
if(cfs_b->quota==RUNTIME_INF)
amount=min_amount;
else{
//保證定時(shí)器是打開(kāi)的,保證周期性地為任務(wù)組重置帶寬時(shí)間
start_cfs_bandwidth(cfs_b);

//如果本周期內(nèi)還有時(shí)間,則可以分配
if(cfs_b->runtime>0){
//確保不要透支
amount=min(cfs_b->runtime,min_amount);
cfs_b->runtime-=amount;
cfs_b->idle=0;
}
}

cfs_rq->runtime_remaining+=amount;
returncfs_rq->runtime_remaining>0;
}

首先,獲取當(dāng)前 task_group 的 cfs_bandwidth,因?yàn)檎麄€(gè)任務(wù)組的帶寬數(shù)據(jù)都是封裝在這里的。接著調(diào)用 sched_cfs_bandwidth_slice 來(lái)獲取后面要留有多長(zhǎng)時(shí)間,這個(gè)函數(shù)訪問(wèn)的 sysctl 下的 sched_cfs_bandwidth_slice 參數(shù)。

//file:kernel/sched/fair.c
staticinlineu64sched_cfs_bandwidth_slice(void)
{
return(u64)sysctl_sched_cfs_bandwidth_slice*NSEC_PER_USEC;
}

這個(gè)參數(shù)在我的機(jī)器上是 5000 us(也就是說(shuō)每次申請(qǐng) 5 ms)。

$sysctl-a|grepsched_cfs_bandwidth_slice
kernel.sched_cfs_bandwidth_slice_us=5000

在計(jì)算要申請(qǐng)的時(shí)間的時(shí)候,還需要考慮現(xiàn)在有多少時(shí)間。如果 cfs_rq->runtime_remaining 為正的話,那可以少申請(qǐng)一點(diǎn),如果已經(jīng)變?yōu)樨?fù)數(shù)的話,需要在 sched_cfs_bandwidth_slice 基礎(chǔ)之上再多申請(qǐng)一些。

所以,最終要申請(qǐng)的時(shí)間值 min_amount = sched_cfs_bandwidth_slice() - cfs_rq->runtime_remaining

計(jì)算出 min_amount 后,直接在向自己所屬的 task_group 下的 cfs_bandwidth 把時(shí)間申請(qǐng)出來(lái)。整個(gè) task_group 下可用的時(shí)間是保存在 cfs_b->runtime 中的。

這里你可能會(huì)問(wèn)了,那 task_group 下的 cfs_b->runtime 的時(shí)間又是哪兒給分配的呢?我們將在 5.1 節(jié)來(lái)討論這個(gè)過(guò)程。

4.2 帶寬限制

check_cfs_rq_runtime 這個(gè)函數(shù)檢測(cè) task group 的帶寬是否已經(jīng)耗盡, 如果是則調(diào)用 throttle_cfs_rq 對(duì)進(jìn)程進(jìn)行限流。

//file:kernel/sched/fair.c
staticboolcheck_cfs_rq_runtime(structcfs_rq*cfs_rq)
{
//判斷是不是時(shí)間余額已用盡
if(likely(!cfs_rq->runtime_enabled||cfs_rq->runtime_remaining>0))
returnfalse;
...

throttle_cfs_rq(cfs_rq);
returntrue;
}

我們?cè)賮?lái)看看 throttle_cfs_rq 的執(zhí)行過(guò)程。

//file:kernel/sched/fair.c
staticvoidthrottle_cfs_rq(structcfs_rq*cfs_rq)
{
//1.查找到所屬的task_group下的se
se=cfs_rq->tg->se[cpu_of(rq_of(cfs_rq))];
...

//2.遍歷每一個(gè)可調(diào)度實(shí)體,并從隸屬的 cfs_rq 上面刪除。
for_each_sched_entity(se){
structcfs_rq*qcfs_rq=cfs_rq_of(se);

if(dequeue)
dequeue_entity(qcfs_rq,se,DEQUEUE_SLEEP);
...
}

//3.設(shè)置一些 throttled 信息。
cfs_rq->throttled=1;
cfs_rq->throttled_clock=rq_clock(rq);

//4.確保unthrottle的高精度定時(shí)器處于被激活的狀態(tài)
start_cfs_bandwidth(cfs_b);
...
}

在 throttle_cfs_rq 中,找到其所屬的 task_group 下的調(diào)度實(shí)體 se 數(shù)組,遍歷每一個(gè)元素,并從其隸屬的 cfs_rq 的紅黑樹(shù)上刪除。這樣下次再調(diào)度的時(shí)候,就不會(huì)再調(diào)度到這些進(jìn)程了。

那么 start_cfs_bandwidth 是干啥的呢?這正好是下一節(jié)的引子。

五、進(jìn)程的可運(yùn)行時(shí)間的分配

在第四小節(jié)我們看到,task_group 下的進(jìn)程的運(yùn)行時(shí)間都是從它的 cfs_b->runtime 中申請(qǐng)的。這個(gè)時(shí)間是在定時(shí)器中分配的。負(fù)責(zé)給 task_group 分配運(yùn)行時(shí)間的定時(shí)器包括兩個(gè),一個(gè)是 period_timer,另一個(gè)是 slack_timer。

structcfs_bandwidth{
ktime_tperiod;
u64    quota;
...
structhrtimerperiod_timer;
structhrtimerslack_timer;
...
}

peroid_timer 是周期性給 task_group 添加時(shí)間,缺點(diǎn)是 timer 周期比較長(zhǎng),通常是100ms。而 slack_timer 用于有 cfs_rq 處于 throttle 狀態(tài)且全局時(shí)間池有時(shí)間供分配但是 period_timer 有還有比較長(zhǎng)時(shí)間(通常大于7ms)才超時(shí)的場(chǎng)景。這個(gè)時(shí)候我們就可以激活比較短的slack_timer(5ms超時(shí))進(jìn)行throttle,這樣的設(shè)計(jì)可以提升系統(tǒng)的實(shí)時(shí)性。

這兩個(gè) timer 在 cgroup 下的 cfs_bandwidth 初始化的時(shí)候,都設(shè)置好了到期回調(diào)函數(shù),分別是 sched_cfs_period_timer 和 sched_cfs_slack_timer。

//file:kernel/sched/fair.c
voidinit_cfs_bandwidth(structcfs_bandwidth*cfs_b)
{
cfs_b->runtime=0;
cfs_b->quota=RUNTIME_INF;
cfs_b->period=ns_to_ktime(default_cfs_period());

//初始化period_timer并設(shè)置回調(diào)函數(shù)
hrtimer_init(&cfs_b->period_timer,CLOCK_MONOTONIC,HRTIMER_MODE_ABS_PINNED);
cfs_b->period_timer.function=sched_cfs_period_timer;

//初始化slack_timer并設(shè)置回調(diào)函數(shù)
hrtimer_init(&cfs_b->slack_timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);
cfs_b->slack_timer.function=sched_cfs_slack_timer;
...
}

在上一節(jié)最后提到的 start_cfs_bandwidth 就是在打開(kāi) period_timer 定時(shí)器。

//file:kernel/sched/fair.c
voidstart_cfs_bandwidth(structcfs_bandwidth*cfs_b)
{
...
hrtimer_forward_now(&cfs_b->period_timer,cfs_b->period);
hrtimer_start_expires(&cfs_b->period_timer,HRTIMER_MODE_ABS_PINNED);
}

在 hrtimer_forward_now 調(diào)用時(shí)傳入的第二個(gè)參數(shù)表示是觸發(fā)的延遲時(shí)間。這個(gè)就是在 cgroup 是設(shè)置的 period,一般為 100 ms。

我們來(lái)分別看看這兩個(gè) timer 是如何給 task_group 定期發(fā)工資(分配時(shí)間)的。

5.1 period_timer

在 period_timer 的回調(diào)函數(shù) sched_cfs_period_timer 中,周期性地為任務(wù)組分配帶寬時(shí)間,并且解掛當(dāng)前任務(wù)組中所有掛起的隊(duì)列。

分配帶寬時(shí)間是在 __refill_cfs_bandwidth_runtime 中執(zhí)行的,它的調(diào)用堆棧如下。

sched_cfs_period_timer
->do_sched_cfs_period_timer
->__refill_cfs_bandwidth_runtime
//file:kernel/sched/fair.c
void__refill_cfs_bandwidth_runtime(structcfs_bandwidth*cfs_b)
{
if(cfs_b->quota!=RUNTIME_INF)
cfs_b->runtime=cfs_b->quota;
}

可見(jiàn),這里直接給 cfs_b->runtime 增加了 cfs_b->quota 這么多的時(shí)間。其中 cfs_b->quota 你就可以認(rèn)為是在 cgroupfs 目錄下,我們配置的那個(gè)值。在第一節(jié)中,我們配置的是 500 ms。

#echo500000>cpu.cfs_period_us//500ms

5.2 slack_timer

設(shè)想一下,假如說(shuō)某個(gè)進(jìn)程申請(qǐng)了 5 ms 的執(zhí)行時(shí)間,但是當(dāng)進(jìn)程剛一啟動(dòng)執(zhí)行便執(zhí)行了同步阻塞的邏輯,這時(shí)候所申請(qǐng)的時(shí)間根本都沒(méi)有用完。在這種情況下,申請(qǐng)但沒(méi)用完的時(shí)間大部分是要返還給 task_group 中的全局時(shí)間池的。

在內(nèi)核中的調(diào)用鏈如下

dequeue_task_fair
–>dequeue_entity
–>return_cfs_rq_runtime
–>__return_cfs_rq_runtime

具體的返還是在 __return_cfs_rq_runtime 中處理的。

//file:kernel/sched/fair.c
staticvoid__return_cfs_rq_runtime(structcfs_rq*cfs_rq)
{
//給自己留一點(diǎn)
s64slack_runtime=cfs_rq->runtime_remaining-min_cfs_rq_runtime;
if(slack_runtime<=?0)
??return;

?//返還到全局時(shí)間池中
?if?(cfs_b->quota!=RUNTIME_INF){
cfs_b->runtime+=slack_runtime;

//如果時(shí)間又足夠多了,并且還有進(jìn)程被限制的話
//則調(diào)用start_cfs_slack_bandwidth來(lái)開(kāi)啟slack_timer
if(cfs_b->runtime>sched_cfs_bandwidth_slice()&&
!list_empty(&cfs_b->throttled_cfs_rq))
start_cfs_slack_bandwidth(cfs_b);
}
...
}

這個(gè)函數(shù)做了這么幾件事情。

min_cfs_rq_runtime 的值是 1 ms,我們選擇至少保留 1ms 時(shí)間給自己

剩下的時(shí)間 slack_runtime 歸還給當(dāng)前的 cfs_b->runtime

如果時(shí)間又足夠多了,并且還有進(jìn)程被限制的話,開(kāi)啟slack_timer,嘗試接觸進(jìn)程 CPU 限制

在 start_cfs_slack_bandwidth 中啟動(dòng)了 slack_timer。

//file:kernel/sched/fair.c
staticvoidstart_cfs_slack_bandwidth(structcfs_bandwidth*cfs_b)
{
...

//啟動(dòng)slack_timer
cfs_b->slack_started=true;
hrtimer_start(&cfs_b->slack_timer,
ns_to_ktime(cfs_bandwidth_slack_period),
HRTIMER_MODE_REL);
...
}

可見(jiàn) slack_timer 的延遲回調(diào)時(shí)間是 cfs_bandwidth_slack_period,它的值是 5 ms。這就比 period_timer 要實(shí)時(shí)多了。

slack_timer 的回調(diào)函數(shù) sched_cfs_slack_timer 我們就不展開(kāi)看了,它主要就是操作對(duì)進(jìn)程解除 CPU 限制

六、總結(jié)

今天我們介紹了 Linux cgroup 的 cpu 子系統(tǒng)給容器中的進(jìn)程分配 cpu 時(shí)間的原理。

和真正使用物理機(jī)不同,Linux 容器中所謂的核并不是真正的 CPU 核,而是轉(zhuǎn)化成了執(zhí)行時(shí)間的概念。在容器進(jìn)程調(diào)度的時(shí)候給其滿足一定的 CPU 執(zhí)行時(shí)間,而不是真正的分配邏輯核。

cgroup 提供了的原生接口是通過(guò) cgroupfs 提供控制各個(gè)子系統(tǒng)的設(shè)置的。默認(rèn)是在 /sys/fs/cgroup/ 目錄下,內(nèi)核這個(gè)文件系統(tǒng)的處理是定義了特殊的處理,和普通的文件完全不一樣的。

內(nèi)核處理 cpu 帶寬控制的核心對(duì)象就是下面這個(gè) cfs_bandwidth。

//file:kernel/sched/sched.h
structcfs_bandwidth{
//帶寬控制配置
ktime_tperiod;
u64quota;

//當(dāng)前task_group的全局可執(zhí)行時(shí)間
u64runtime;
...

//定時(shí)分配
structhrtimerperiod_timer;
structhrtimerslack_timer;
}

用戶在創(chuàng)建 cgroup cpu 子系統(tǒng)控制過(guò)程主要分成三步:

第一步:通過(guò)創(chuàng)建目錄來(lái)創(chuàng)建 cgroup 對(duì)象。在 /sys/fs/cgroup/cpu,cpuacct 創(chuàng)建一個(gè)目錄 test,實(shí)際上內(nèi)核是創(chuàng)建了 cgroup、task_group 等內(nèi)核對(duì)象。

第二步:在目錄中設(shè)置 cpu 的限制情況。在 task_group 下有個(gè)核心的 cfs_bandwidth 對(duì)象,用戶所設(shè)置的 cfs_quota_us 和 cfs_period_us 的值最后都存到它下面了。

第三步:將進(jìn)程添加到 cgroup 中進(jìn)行資源管控。當(dāng)在 cgroup 的 cgroup.proc 下添加進(jìn)程 pid 時(shí),實(shí)際上是將該進(jìn)程加入到了這個(gè)新的 task_group 調(diào)度組了。將使用 task_group 的 runqueue,以及它的時(shí)間配額

當(dāng)創(chuàng)建完成后,內(nèi)核的 period_timer 會(huì)根據(jù) task_group->cfs_bandwidth 下用戶設(shè)置的 period 定時(shí)給可執(zhí)行時(shí)間 runtime 上加上 quota 這么多的時(shí)間(相當(dāng)于按月發(fā)工資),以供 task_group 下的進(jìn)程執(zhí)行(消費(fèi))的時(shí)候使用。

structcfs_rq{
...
intruntime_enabled;
s64runtime_remaining;
}

在完全公平器調(diào)度的時(shí)候,每次 pick_next_task_fair 時(shí)會(huì)做兩件事情

第一件:將從 cpu 上拿下來(lái)的進(jìn)程所在的運(yùn)行隊(duì)列進(jìn)行執(zhí)行時(shí)間的更新與申請(qǐng)。會(huì)將 cfs_rq 的 runtime_remaining 減去已經(jīng)執(zhí)行了的時(shí)間。如果減為了負(fù)數(shù),則從 cfs_rq 所在的 task_group 下的 cfs_bandwidth 去申請(qǐng)一些。

第二件:判斷 cfs_rq 上是否申請(qǐng)到了可執(zhí)行時(shí)間,如果沒(méi)有申請(qǐng)到,需要將這個(gè)隊(duì)列上的所有進(jìn)程都從完全公平調(diào)度器的紅黑樹(shù)上取下。這樣再次調(diào)度的時(shí)候,這些進(jìn)程就不會(huì)被調(diào)度了。

當(dāng) period_timer 再次給 task_group 分配時(shí)間的時(shí)候,或者是自己有申請(qǐng)時(shí)間沒(méi)用完回收后觸發(fā) slack_timer 的時(shí)候,被限制調(diào)度的進(jìn)程會(huì)被解除調(diào)度限制,重新正常參與運(yùn)行。

這里要注意的是,一般 period_timer 分配時(shí)間的周期都是 100 ms 左右。假如說(shuō)你的進(jìn)程前 50 ms 就把 cpu 給用光了,那你收到的請(qǐng)求可能在后面的 50 ms 都沒(méi)有辦法處理,對(duì)請(qǐng)求處理耗時(shí)會(huì)有影響。這也是為啥在關(guān)注 CPU 性能的時(shí)候要關(guān)注對(duì)容器 throttle 次數(shù)和時(shí)間的原因了。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11497

    瀏覽量

    213267
  • 調(diào)度器
    +關(guān)注

    關(guān)注

    0

    文章

    98

    瀏覽量

    5478

原文標(biāo)題:內(nèi)核是如何給容器中的進(jìn)程分配CPU資源的?

文章出處:【微信號(hào):良許Linux,微信公眾號(hào):良許Linux】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    CPU底層工作原理

    前段時(shí)間,我連續(xù)寫(xiě)了十來(lái)篇CPU底層系列技術(shù)故事文章,有不少讀者私信我讓我寫(xiě)一CPU的寄存器。
    發(fā)表于 07-25 10:20 ?1858次閱讀

    Linux開(kāi)發(fā)_Linux進(jìn)程編程

    介紹Linux進(jìn)程概念、進(jìn)程信號(hào)捕獲、進(jìn)程管理相關(guān)的命令的使用等知識(shí)點(diǎn)。
    的頭像 發(fā)表于 09-17 15:38 ?1640次閱讀
    <b class='flag-5'>Linux</b>開(kāi)發(fā)_<b class='flag-5'>Linux</b><b class='flag-5'>下</b><b class='flag-5'>進(jìn)程</b>編程

    Linux進(jìn)程怎么綁定CPU

    昨天在群里有朋友問(wèn):把進(jìn)程綁定到某個(gè) CPU 上運(yùn)行是怎么實(shí)現(xiàn)的。
    發(fā)表于 10-26 10:26 ?2043次閱讀

    Linux系統(tǒng)進(jìn)程的幾種狀態(tài)介紹

    文章對(duì) Linux 系統(tǒng)進(jìn)程的幾種狀態(tài)進(jìn)行介紹,并對(duì)系統(tǒng)出現(xiàn)大量僵尸進(jìn)程和不可中斷進(jìn)程的場(chǎng)景
    發(fā)表于 11-24 16:15 ?1.4w次閱讀
    <b class='flag-5'>Linux</b>系統(tǒng)<b class='flag-5'>下</b><b class='flag-5'>進(jìn)程</b>的幾種狀態(tài)介紹

    Linux進(jìn)程的睡眠和喚醒

    Linux中,僅等待CPU時(shí)間的進(jìn)程稱為就緒進(jìn)程,它們被放置在一個(gè)運(yùn)行隊(duì)列中,一個(gè)就緒進(jìn)程的狀 態(tài)標(biāo)志位為 TASK_RUNNING。一旦
    發(fā)表于 06-07 12:26 ?611次閱讀

    Linux進(jìn)程結(jié)構(gòu)

    `#嵌入式培訓(xùn)#華清遠(yuǎn)見(jiàn)嵌入式linux學(xué)習(xí)資料《Linux進(jìn)程結(jié)構(gòu)》,進(jìn)程不但包括程序的指令和數(shù)據(jù),而且包括程序計(jì)數(shù)器和處理器的所有寄
    發(fā)表于 08-05 11:05

    Linux進(jìn)程結(jié)構(gòu)

    (TASK_KILLABLE):Linux內(nèi)核 2.6.25 引入了一種新的進(jìn)程狀態(tài),名為 TASK_KILLABLE。該狀態(tài)的運(yùn)行機(jī)制類似于 TASK_UNINTERRUPTIBLE,只不過(guò)處在該狀態(tài)
    發(fā)表于 05-27 09:24

    linux操作系統(tǒng)進(jìn)程通信設(shè)計(jì)

    linux進(jìn)程通信手段基本上是從Unix平臺(tái)上的進(jìn)程通信手段繼承而來(lái)的。而對(duì)Unix發(fā)展做出重大貢獻(xiàn)的兩大主力AT&T的貝
    發(fā)表于 11-24 10:53 ?817次閱讀

    linux操作系統(tǒng)進(jìn)程通信

    的側(cè)重點(diǎn)有所不同。前者對(duì)Unix早期的進(jìn)程間通信手段進(jìn)行了系統(tǒng)的改進(jìn)和擴(kuò)充,形成了system V IPC,通信進(jìn)程局限在單個(gè)計(jì)算機(jī)內(nèi);后者則跳過(guò)了該限制,形成了基于套接口(socke
    發(fā)表于 10-31 11:15 ?0次下載

    詳解如何監(jiān)控和保護(hù)Linux進(jìn)程安全

    。 經(jīng)典的信息保密性安全模型Bell-LaPadula模型指出,進(jìn)程是整個(gè)計(jì)算機(jī)系統(tǒng)的一個(gè)主體,它需要通過(guò)一定的安全等級(jí)來(lái)對(duì)客體發(fā)生作用。進(jìn)程在一定條件可以對(duì)諸如文件、數(shù)據(jù)庫(kù)等客體進(jìn)行
    發(fā)表于 11-06 11:20 ?0次下載

    Linux CPU的性能應(yīng)該如何優(yōu)化

    Linux系統(tǒng)中,由于成本的限制,往往會(huì)存在資源上的不足,例如 CPU、內(nèi)存、網(wǎng)絡(luò)、IO 性能。本文,就對(duì) Linux 進(jìn)程
    的頭像 發(fā)表于 01-18 08:52 ?3686次閱讀

    基于linux eBPF的進(jìn)程off-cpu的方法

    的swap等。如下圖所示,紅色部分屬于on-cpu部分,藍(lán)色部分屬于off-cpu。 一般我們用的perf命令等都是采樣on-cpu的指令進(jìn)行CPU
    的頭像 發(fā)表于 09-25 15:41 ?3384次閱讀
    基于<b class='flag-5'>linux</b> eBPF的<b class='flag-5'>進(jìn)程</b>off-<b class='flag-5'>cpu</b>的方法

    Linux技術(shù)中Cgroup的原理和實(shí)踐

    一、什么是Cgroup,使用場(chǎng)景? 容器本質(zhì)上是進(jìn)程,既然是進(jìn)程就會(huì)消耗掉系統(tǒng)資源,比如:CPU、內(nèi)存、磁盤(pán)、網(wǎng)絡(luò)帶寬等,如果不加以限制
    的頭像 發(fā)表于 10-15 14:04 ?5126次閱讀
    <b class='flag-5'>Linux</b>技術(shù)中Cgroup的原理和實(shí)踐

    如何將進(jìn)程CPU 進(jìn)行綁定

    Linux 系統(tǒng)提供了一個(gè)名為 sched_setaffinity 的系統(tǒng)調(diào)用,此系統(tǒng)調(diào)用可以設(shè)置進(jìn)程CPU 親和性。我們來(lái)看看 sched_setaffinity 系統(tǒng)調(diào)用的原型。
    發(fā)表于 10-26 10:29 ?645次閱讀

    如何限制容器可以使用的CPU資源

    默認(rèn)情況容器可以使用的主機(jī) CPU 資源是不受限制的。和內(nèi)存資源的使用一樣,如果不對(duì)容器可以使用的 C
    的頭像 發(fā)表于 10-24 17:04 ?645次閱讀
    如何<b class='flag-5'>限制</b><b class='flag-5'>容器</b>可以使用的<b class='flag-5'>CPU</b>資源
    主站蜘蛛池模板: 黄浦区| 南江县| 垣曲县| 桐乡市| 公安县| 车致| 军事| 灌云县| 安化县| 施甸县| 阜阳市| 兴安县| 四会市| 安乡县| 浠水县| 鹿邑县| 延津县| 监利县| 梁山县| 南安市| 龙海市| 宜黄县| 顺昌县| 原平市| 色达县| 韶关市| 密山市| 武乡县| 平乡县| 温宿县| 金昌市| 防城港市| 繁昌县| 颍上县| 比如县| 修文县| 凤凰县| 唐海县| 铜川市| 兴宁市| 海原县|