哈哈哈哈哈操欧洲电影,久草网在线,亚洲久久熟女熟妇视频,麻豆精品色,久久福利在线视频,日韩中文字幕的,淫乱毛视频一区,亚洲成人一二三,中文人妻日韩精品电影

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

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

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

Linux內(nèi)核睡眠的三種狀態(tài)講解

B4Pb_gh_6fde77c ? 來源:Linux內(nèi)核遠(yuǎn)航者 ? 作者:Linux內(nèi)核遠(yuǎn)航者 ? 2021-08-16 15:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1開場白

環(huán)境:

處理器架構(gòu):arm64

內(nèi)核源碼:linux-5.10.50

ubuntu版本:20.04.1

代碼閱讀工具:vim+ctags+cscope

無論是任務(wù)處于用戶態(tài)還是內(nèi)核態(tài),經(jīng)常會(huì)因?yàn)榈却承┦录撸赡苁堑却齀O讀寫完成,也可能等待其他內(nèi)核路徑釋放一把鎖等)。本文來探討一下,任務(wù)處于睡眠中有哪些狀態(tài)?睡眠對(duì)于任務(wù)來說究竟意味著什么?內(nèi)核是如何管理睡眠的任務(wù)的?我們會(huì)結(jié)合內(nèi)核源代碼來分析任務(wù)的睡眠,力求全方位角度來剖析。

注:由于篇幅問題,文章分為上下兩篇,且這里不區(qū)分進(jìn)程和任務(wù),統(tǒng)一使用任務(wù)來表示進(jìn)程。

主要講解以下內(nèi)容:

睡眠的三種狀態(tài)

睡眠的內(nèi)核原理

用戶態(tài)睡眠

內(nèi)核態(tài)睡眠

總結(jié)

2. 睡眠的三種狀態(tài)

任務(wù)睡眠有三種狀態(tài):

淺度睡眠

中度睡眠

深度睡眠

2.1 淺度睡眠

進(jìn)程描述符的state使用TASK_INTERRUPTIBLE表示這種狀態(tài)。

為可中斷的睡眠狀態(tài),這里可中斷是可以被信號(hào)所打斷(喚醒)。

這里給出被信號(hào)打斷/喚醒的代碼路徑:

kernel/signal.c

SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)

->kill_something_info

->__kill_pgrp_info

->group_send_sig_info

->do_send_sig_info

->send_signal

->__send_signal

->complete_signal

->signal_wake_up

-> signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0)

->wake_up_state(t, state | TASK_INTERRUPTIBLE)

->try_to_wake_up

可以看到在信號(hào)傳遞的時(shí)候,會(huì)通過signal_wake_up喚醒從處于可中斷睡眠狀態(tài)的任務(wù)。

2.2 中度睡眠

進(jìn)程描述符的state使用TASK_KILLABLE表示這種狀態(tài)。

可以被致命信號(hào)所打斷。

這里給出被致命信號(hào)打斷/喚醒的代碼路徑:

include/linux/sched.h

#define TASK_KILLABLE (TASK_WAKEKILL | TASK_UNINTERRUPTIBLE)

kernel/signal.c

SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)

->kill_something_info

->__kill_pgrp_info

->group_send_sig_info

->do_send_sig_info

->send_signal

->__send_signal

->complete_signal

->

if (sig_fatal(p, sig) &&

| ?。╯ignal->flags & SIGNAL_GROUP_EXIT) &&

| !sigismember(&t->real_blocked, sig) &&

| (sig == SIGKILL || !p->ptrace)) { //致命信號(hào)

...

signal_wake_up(t, 1);

-> signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0) // resume == 1

-> wake_up_state(t, state | TASK_INTERRUPTIBLE)

->try_to_wake_up

...

}

2.3 深度睡眠

進(jìn)程描述符的state使用TASK_UNINTERRUPTIBLE表示這種狀態(tài)。

為不可中斷的睡眠狀態(tài),不能被任何信號(hào)所喚醒(特定條件沒有滿足發(fā)生信號(hào)喚醒可能導(dǎo)致數(shù)據(jù)不一致等問題,這種場景使用這種睡眠狀態(tài),如等待IO讀寫完成)。

3. 睡眠的內(nèi)核原理

睡眠都是主動(dòng)發(fā)生調(diào)度,即主動(dòng)調(diào)用主調(diào)度器。

睡眠的主要步驟如下:

1)設(shè)置任務(wù)狀態(tài)為睡眠狀態(tài)

2)記錄睡眠的任務(wù)

3)發(fā)起主動(dòng)調(diào)度

下面我們來詳細(xì)解讀下這幾個(gè)步驟:

3.1 設(shè)置任務(wù)狀態(tài)為睡眠狀態(tài)

這一步很有必要,一來標(biāo)識(shí)進(jìn)入了睡眠狀態(tài),二來是主調(diào)度器會(huì)根據(jù)睡眠標(biāo)志將任務(wù)從運(yùn)行隊(duì)列刪除。

注:睡眠狀態(tài)描述見上一小節(jié)!

3.2 記錄睡眠的任務(wù)

這一步也非常有必要,內(nèi)核會(huì)將即將睡眠的任務(wù)記錄下來,要么加入到鏈表中管理,要么使用數(shù)據(jù)結(jié)構(gòu)記錄。

如延遲睡眠場景,內(nèi)核將即將睡眠的任務(wù)記錄在定時(shí)器相關(guān)的數(shù)據(jù)結(jié)構(gòu)中;可睡眠的信號(hào)量場景中,內(nèi)核將即將睡眠的任務(wù)加入到信號(hào)量的相關(guān)鏈表中。

記錄的目的在于:當(dāng)喚醒條件滿足時(shí),喚醒函數(shù)能夠找到想要喚醒的任務(wù)。

3.3 發(fā)起主動(dòng)調(diào)度

這一步是真正進(jìn)行睡眠的操作,主要是調(diào)用主調(diào)度器來發(fā)起主動(dòng)調(diào)度讓出處理器。

下面我們來看下主調(diào)度器為任務(wù)睡眠所作的處理:

kernel/sched/core.c

__schedule

->

prev_state = prev->state; //獲得前一個(gè)任務(wù)狀態(tài)

if (!preempt && prev_state) { //如果是主動(dòng)調(diào)度 且任務(wù)狀態(tài)不為0

if (signal_pending_state(prev_state, prev)) { //有掛起的信號(hào)

prev->state = TASK_RUNNING; //設(shè)置狀態(tài)為可運(yùn)行

} else {

deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK); //cpu運(yùn)行隊(duì)列中刪除任務(wù)

}

}

next = pick_next_task(rq, prev, &rf); //選擇下一個(gè)任務(wù)

context_switch //進(jìn)行上下文切換

來看下deactivate_task對(duì)于睡眠任務(wù)做的主要工作:

deactivate_task

->deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK)

->p->on_rq = (flags & DEQUEUE_SLEEP) ? 0 : TASK_ON_RQ_MIGRATING; //設(shè)置任務(wù)的on_rq 為0 標(biāo)識(shí)是睡眠

dequeue_task(rq, p, flags);

->p->sched_class->dequeue_task(rq, p, flags)

->dequeue_task_fair

->dequeue_entity

...

if (se != cfs_rq->curr) //不是cpu當(dāng)前 任務(wù)

__dequeue_entity(cfs_rq, se); //cfs運(yùn)行隊(duì)列刪除

->se->on_rq = 0; //標(biāo)識(shí)調(diào)度實(shí)體不在運(yùn)行隊(duì)列?。?!

->if (!(flags & DEQUEUE_SLEEP))

se->vruntime -= cfs_rq->min_vruntime; //調(diào)度實(shí)體的虛擬運(yùn)行時(shí)間 減去 cfs運(yùn)行隊(duì)列的最小虛擬運(yùn)行時(shí)間

deactivate_task會(huì)設(shè)置任務(wù)的on_rq 為0來 標(biāo)識(shí)是睡眠 ,然后 調(diào)用到調(diào)度類的dequeue_task方法,在cfs中設(shè)置se->on_rq = 0標(biāo)識(shí)調(diào)度實(shí)體不在cfs隊(duì)列。

可以看到,發(fā)起主動(dòng)調(diào)度的時(shí)候,在主調(diào)度器中會(huì)做判斷:如果是主動(dòng)調(diào)度且任務(wù)狀態(tài)不為0 (即為不是可運(yùn)行的TASK_RUNNING)時(shí),如果沒有掛起的信號(hào),就會(huì)將任務(wù)從cpu的運(yùn)行隊(duì)列中“刪除”,然后選擇下一個(gè)任務(wù),進(jìn)行上下文切換。

將即將睡眠的任務(wù)從cpu的運(yùn)行隊(duì)列中“刪除”意義重大:主調(diào)度器再次選擇下一個(gè)任務(wù)的時(shí)候不會(huì)在選擇睡眠的任務(wù)(因?yàn)橹髡{(diào)度器總是在運(yùn)行隊(duì)列中選擇任務(wù)運(yùn)行,除非任務(wù)被喚醒,重新加入運(yùn)行隊(duì)列)。

注意:1.這里的刪除指的是設(shè)置對(duì)應(yīng)標(biāo)志如p->on_rq=0,se->on_rq = 0,當(dāng)選擇下一個(gè)任務(wù)的時(shí)候不會(huì)在加入運(yùn)行隊(duì)列中。2.即將睡眠的任務(wù)是cpu上的當(dāng)前任務(wù)(curr指向)。3.調(diào)用主調(diào)度器后,即將睡眠的任務(wù)不會(huì)再次加入cpu運(yùn)行隊(duì)列,除非被喚醒。

再來看下選擇下一個(gè)任務(wù)的時(shí)候會(huì)做哪些事情和睡眠有關(guān)(暫不考慮組調(diào)度情況):

pick_next_task

->class->pick_next_task

->pick_next_task_fair //kernel/sched/fair.c

->if (prev)

put_prev_task(rq, prev); //對(duì)前一個(gè)任務(wù)處理

se = pick_next_entity(cfs_rq, NULL); //選擇下一個(gè)任務(wù)

set_next_entity(cfs_rq, se);

主要看下put_prev_task:

put_prev_task

->prev->sched_class->put_prev_task(rq, prev)

->put_prev_task_fair

->put_prev_entity

-> if (prev->on_rq) { //前一個(gè)任務(wù)的調(diào)度實(shí)體on_rq不為0?

update_stats_wait_start(cfs_rq, prev);

/* Put ‘current’ back into the tree. */

__enqueue_entity(cfs_rq, prev); //重新加入cfs運(yùn)行隊(duì)列

/* in !on_rq case, update occurred at dequeue */

update_load_avg(cfs_rq, prev, 0);

}

cfs_rq->curr = NULL; //設(shè)置cfs運(yùn)行隊(duì)列的curr為NULL

put_prev_task所做的主要工作就是將前一個(gè)任務(wù)從cfs運(yùn)行隊(duì)列中刪除,在這里就是通過調(diào)用__enqueue_entity將對(duì)應(yīng)的調(diào)度實(shí)體重新加入cfs隊(duì)列的紅黑樹,但是對(duì)于即將睡眠的任務(wù)之前在主調(diào)度器中通過deactivate_task將prev->on_rq設(shè)置為0了,所以對(duì)于即將睡眠的任務(wù)來說,它對(duì)應(yīng)的調(diào)度實(shí)體不會(huì)在重新加入cfs運(yùn)行隊(duì)列的紅黑樹。

責(zé)任編輯:haq

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

    關(guān)注

    4

    文章

    1474

    瀏覽量

    43087
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11806

    瀏覽量

    219482

原文標(biāo)題:深入理解Linux內(nèi)核之進(jìn)程睡眠(上)

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

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

    如何理解Linux內(nèi)核中的PCIe驅(qū)動(dòng)

    我們習(xí)慣了用 Verilog 去死磕 PCIe 的底層協(xié)議狀態(tài)機(jī)。但一旦越過硬件邊界來到操作系統(tǒng)層面,Linux 內(nèi)核是如何接管并驅(qū)動(dòng)這些 PCI/PCIe 設(shè)備的呢?由于不同的 CPU 架構(gòu)實(shí)現(xiàn)了
    的頭像 發(fā)表于 04-11 17:22 ?1171次閱讀

    AP6301 低功耗模式對(duì)比:待機(jī) / 關(guān)斷 / 睡眠(功耗實(shí)測)

    AP6301 三種低功耗模式,滿足不同產(chǎn)品待機(jī)需求: 充電完成待機(jī) :≈85μA 關(guān)斷模式 (PROG 懸空) :≈25μA 睡眠 (VCC 掉電) :電池反向漏電流 <1μA 實(shí)測案例 : TWS 充電倉,5V 輸入,充滿后自動(dòng)進(jìn)入待機(jī), 月自耗電<1% ,完全滿足長續(xù)
    發(fā)表于 04-11 11:02

    Linux內(nèi)核大核心模塊深度解析:調(diào)度、內(nèi)存與I/O

    Linux內(nèi)核作為操作系統(tǒng)的核心,其進(jìn)程調(diào)度、內(nèi)存管理和文件I/O大模塊共同決定了系統(tǒng)的性能與穩(wěn)定性。無論是多核服務(wù)器的高并發(fā)處理,還是嵌入式設(shè)備的資源受限場景,深入理解這些底層機(jī)制都是進(jìn)行性能調(diào)
    的頭像 發(fā)表于 03-12 09:00 ?215次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b><b class='flag-5'>三</b>大核心模塊深度解析:調(diào)度、內(nèi)存與I/O

    深度解析ES8389/ES8390/音頻芯片Linux驅(qū)動(dòng)(Linux6.1內(nèi)核

    基于 Linux6.1 內(nèi)核,從驅(qū)動(dòng)架構(gòu)、寄存器配置、核心函數(shù)、數(shù)據(jù)流走向四個(gè)維度,完整拆解 ES8389 的 Linux 驅(qū)動(dòng)實(shí)現(xiàn),幫你吃透這款芯片的驅(qū)動(dòng)邏輯。 ? ? 注意:在講解
    的頭像 發(fā)表于 02-02 11:37 ?2232次閱讀
    深度解析ES8389/ES8390/音頻芯片<b class='flag-5'>Linux</b>驅(qū)動(dòng)(<b class='flag-5'>Linux</b>6.1<b class='flag-5'>內(nèi)核</b>)

    Linux系統(tǒng)內(nèi)核參數(shù)調(diào)優(yōu)實(shí)戰(zhàn)指南

    Linux 內(nèi)核參數(shù)調(diào)優(yōu)是系統(tǒng)性能優(yōu)化的核心環(huán)節(jié)。隨著云原生架構(gòu)的普及和硬件性能的飛速提升,默認(rèn)的內(nèi)核參數(shù)配置往往無法充分發(fā)揮系統(tǒng)潛力。在高并發(fā) Web 服務(wù)、大數(shù)據(jù)處理、容器化部署等場景下,合理的
    的頭像 發(fā)表于 01-28 14:27 ?659次閱讀

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】+讀深入理解Linux內(nèi)核內(nèi)存分配

    每個(gè)內(nèi)存地址是虛擬的,不是直接指向RAM中的任何地址。當(dāng)用戶訪問內(nèi)存中的存儲(chǔ)單元時(shí),都會(huì)進(jìn)行地址轉(zhuǎn)換以匹配相應(yīng)的物理內(nèi)存。書籍的第10章討論了五個(gè)主題,對(duì)Linux內(nèi)核內(nèi)存分配進(jìn)行詳細(xì)講解。 接著
    發(fā)表于 01-16 20:05

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】Linux內(nèi)核開發(fā)基礎(chǔ)

    隊(duì)列中的元素就是正在睡眠且等待被喚醒的進(jìn)程 內(nèi)核中的簡單睡眠 簡單睡眠也被稱為被動(dòng)睡眠,任務(wù)會(huì)在等待時(shí)進(jìn)入
    發(fā)表于 01-12 22:45

    【「Linux 設(shè)備驅(qū)動(dòng)開發(fā)(第 2 版)」閱讀體驗(yàn)】+讀內(nèi)核處理的核心輔助函數(shù)

    、一些需要等待資源狀態(tài)的改變情況而設(shè)定的。為用戶更好得利用條件變量,Linux內(nèi)核提供了等待隊(duì)列、完成隊(duì)列兩機(jī)制。 關(guān)于鎖方面,書籍中介紹相當(dāng)全面。①.自旋鎖,自旋鎖應(yīng)用中存在的弊端
    發(fā)表于 01-10 22:08

    請(qǐng)問CW32芯片的三種工作模式是什么?

    CW32芯片的三種工作模式是什么?
    發(fā)表于 12-26 06:48

    基于 DR1M90 的 Linux-RT 內(nèi)核開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    本手冊(cè)由創(chuàng)龍科技研發(fā),針對(duì) DR1M90,詳述 Linux-RT 實(shí)時(shí)內(nèi)核開發(fā):含實(shí)時(shí)性測試(LinuxLinux-RT 對(duì)比、CPU 空載 / 滿負(fù)荷 / 隔離
    的頭像 發(fā)表于 12-02 10:38 ?1287次閱讀
    基于 DR1M90 的 <b class='flag-5'>Linux</b>-RT <b class='flag-5'>內(nèi)核</b>開發(fā):從編譯配置到 GPIO / 按鍵應(yīng)用實(shí)現(xiàn)(1)

    如何將 GPIO PWM 和 GPIO Capture 驅(qū)動(dòng)程序?qū)?Linux 內(nèi)核,實(shí)現(xiàn) PWM 輸出并檢測引腳的變化狀態(tài)?

    如何將 GPIO PWM 和 GPIO Capture 驅(qū)動(dòng)程序?qū)?Linux 內(nèi)核,實(shí)現(xiàn) PWM 輸出并檢測引腳的變化狀態(tài)
    發(fā)表于 08-20 08:20

    睡眠障礙調(diào)控系列之經(jīng)顱振蕩直流電刺激(toDCS)

    1.睡眠障礙的類型與表征睡眠障礙其類型超80,其中最常見的三種類型及其表征如下:類型核心表征具體描述慢性失眠癥長期入睡困難或睡眠維持障礙持
    的頭像 發(fā)表于 08-13 19:16 ?1167次閱讀
    <b class='flag-5'>睡眠</b>障礙調(diào)控系列之經(jīng)顱振蕩直流電刺激(toDCS)

    MEMS中的三種測溫方式

    在集成MEMS芯片的環(huán)境溫度測量領(lǐng)域,熱阻、熱電堆和PN結(jié)原理是三種主流技術(shù)。熱阻是利用熱敏電阻,如金屬鉑或注入硅的溫度電阻系數(shù)恒定,即電阻隨溫度線性變化的特性測溫,電阻變化直接對(duì)應(yīng)絕對(duì)溫度,需恒流源供電。
    的頭像 發(fā)表于 07-16 13:58 ?1860次閱讀
    MEMS中的<b class='flag-5'>三種</b>測溫方式

    如何配置和驗(yàn)證Linux內(nèi)核參數(shù)

    Linux系統(tǒng)運(yùn)維和性能優(yōu)化中,內(nèi)核參數(shù)(sysctl)的配置至關(guān)重要。合理的參數(shù)調(diào)整可以顯著提升網(wǎng)絡(luò)性能、系統(tǒng)穩(wěn)定性及資源利用率。然而,僅僅修改參數(shù)是不夠的,如何驗(yàn)證這些參數(shù)是否生效同樣關(guān)鍵。
    的頭像 發(fā)表于 05-29 17:40 ?1329次閱讀

    介紹三種常見的MySQL高可用方案

    在生產(chǎn)環(huán)境中,為了確保數(shù)據(jù)庫系統(tǒng)的連續(xù)可用性、降低故障恢復(fù)時(shí)間以及實(shí)現(xiàn)業(yè)務(wù)的無縫切換,高可用(High Availability, HA)方案至關(guān)重要。本文將詳細(xì)介紹三種常見的 MySQL 高可用
    的頭像 發(fā)表于 05-28 17:16 ?1408次閱讀
    望都县| 彰化县| 长宁区| 宜兴市| 滦平县| 酒泉市| 化州市| 哈尔滨市| 永济市| 天水市| 襄城县| 寿阳县| 毕节市| 永修县| 天峻县| 昌邑市| 普兰县| 蛟河市| 河池市| 台中县| 青冈县| 赤壁市| 贡山| 宣城市| 攀枝花市| 鄂托克旗| 淮阳县| 江孜县| 侯马市| 南安市| 华蓥市| 民乐县| 历史| 娄烦县| 建阳市| 宜城市| 彭山县| 芒康县| 安西县| 通渭县| 松桃|