91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

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:06 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

4.用戶態(tài)睡眠

以sleep為例來說明任務(wù)在用戶態(tài)是如何睡眠的。

首先我們通過strace工具來看下其調(diào)用的系統(tǒng)調(diào)用:

$ strace sleep 1

...

close(3) = 0

clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, NULL) = 0

close(1) = 0

...

可以發(fā)現(xiàn)sleep主要調(diào)用clock_nanosleep系統(tǒng)調(diào)用來進(jìn)行睡眠(也就是說用戶態(tài)任務(wù)睡眠需要調(diào)用系統(tǒng)調(diào)用陷入內(nèi)核)。

下面我們來研究下clock_nanosleep的實(shí)現(xiàn)(這里集中到睡眠的實(shí)現(xiàn),先忽略掉定時(shí)器等諸多的技術(shù)細(xì)節(jié)):

kernel/time/posix-timers.c

SYSCALL_DEFINE4(clock_nanosleep

-》const struct k_clock *kc = clockid_to_kclock(which_clock); //根據(jù)時(shí)鐘類型得到內(nèi)核時(shí)鐘結(jié)構(gòu)

return kc-》nsleep(which_clock, flags, &t); //調(diào)用內(nèi)核時(shí)鐘結(jié)構(gòu)的nsleep回調(diào)

我們傳遞過來的時(shí)鐘類型為CLOCK_REALTIME,則調(diào)用鏈為:

kc-》nsleep(CLOCK_REALTIME, flags, &t)

-》clock_realtime.nsleep

-》common_nsleep

-》hrtimer_nanosleep //kernel/time/hrtimer.c

-》hrtimer_init_sleeper_on_stack

-》__hrtimer_init_sleeper

-》__hrtimer_init(&sl-》timer, clock_id, mode); //初始化高精度定時(shí)器

sl-》timer.function = hrtimer_wakeup; //設(shè)置超時(shí)回調(diào)函數(shù)

sl-》task = current;。//設(shè)置超時(shí)時(shí)要喚醒的任務(wù)

-》do_nanosleep //睡眠操作

可以看到,睡眠函數(shù)最終調(diào)用到hrtimer_nanosleep,它調(diào)用了兩個(gè)主要函數(shù):__hrtimer_init_sleeper和do_nanosleep,前者主要設(shè)置高精度定時(shí)器,后者就是真正的睡眠,主要來看下do_nanosleep:

kernel/time/hrtimer.c

do_nanosleep

-》

do {

set_current_state(TASK_INTERRUPTIBLE); //設(shè)置可中斷的睡眠狀態(tài)

hrtimer_sleeper_start_expires(t, mode); //開啟高精度定時(shí)器

if (likely(t-》task))

freezable_schedule(); //主動(dòng)調(diào)度

hrtimer_cancel(&t-》timer);

mode = HRTIMER_MODE_ABS;

} while (t-》task && !signal_pending(current)); //是否記錄的有任務(wù)且沒有掛起的信號(hào)

__set_current_state(TASK_RUNNING); //設(shè)置為可運(yùn)行狀態(tài)

do_nanosleep函數(shù)是睡眠的核心實(shí)現(xiàn):首先設(shè)置任務(wù)的狀態(tài)為可中斷的睡眠狀態(tài),然后開啟了之前設(shè)置的高精度定時(shí)器,隨即調(diào)用freezable_schedule進(jìn)行真正的睡眠。

來看下freezable_schedule:

//include/linux/freezer.h

freezable_schedule

-》schedule()

-》__schedule(false);

可以看到最終調(diào)用主調(diào)度器__schedule進(jìn)行主動(dòng)調(diào)度。

當(dāng)任務(wù)睡眠完成,定時(shí)器超時(shí),會(huì)調(diào)用之前在__hrtimer_init_sleeper設(shè)置的超時(shí)回調(diào)函數(shù)hrtimer_wakeup將睡眠的任務(wù)喚醒(關(guān)于進(jìn)程喚醒在這里就不在贅述,在后面的進(jìn)程喚醒專題文章在進(jìn)行詳細(xì)解讀),然后就可以再次獲得處理器的使用權(quán)了。

總結(jié):處于用戶態(tài)的任務(wù),如果想要睡眠一段時(shí)間必須向內(nèi)核請(qǐng)求服務(wù)(如調(diào)用clock_nanosleep系統(tǒng)調(diào)用),內(nèi)核中會(huì)設(shè)置一個(gè)高精度定時(shí)器,來記錄要睡眠的任務(wù),然后設(shè)置任務(wù)狀態(tài)為可中斷的睡眠狀態(tài),緊接著發(fā)生主動(dòng)調(diào)度,這樣任務(wù)就發(fā)生睡眠了。

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

當(dāng)任務(wù)處于內(nèi)核態(tài)時(shí),有時(shí)候也需要睡眠一段時(shí)間,不像任務(wù)處于用戶態(tài)需要發(fā)生系統(tǒng)調(diào)用來請(qǐng)求內(nèi)核進(jìn)行睡眠,在內(nèi)核態(tài)可以直接調(diào)用睡眠函數(shù)。當(dāng)然,內(nèi)核態(tài)中,睡眠有兩種場(chǎng)景:一種是睡眠特定的時(shí)間的延遲操作(喚醒條件為超時(shí)),一種是等待特定條件滿足(如IO讀寫完成,可睡眠的鎖被釋放等)。

下面分別以msleep和mutex鎖為例講解內(nèi)核態(tài)睡眠:

5.1 msleep

msleep做ms級(jí)別的睡眠延遲。

//kernel/time/timer.c

void msleep(unsigned int msecs)

{

unsigned long timeout = msecs_to_jiffies(msecs) + 1; //ms時(shí)間轉(zhuǎn)換為jiffies

while (timeout)

timeout = schedule_timeout_uninterruptible(timeout); //不可中斷睡眠

}

下面看下schedule_timeout_uninterruptible:

這里涉及到一個(gè)重要數(shù)據(jù)結(jié)構(gòu)process_timer

struct process_timer {

struct timer_list timer; //定時(shí)器結(jié)構(gòu)

struct task_struct *task; //定時(shí)器到期要喚醒的任務(wù)

};

schedule_timeout_uninterruptible

-》 __set_current_state(TASK_UNINTERRUPTIBLE); //設(shè)置任務(wù)狀態(tài)為不可中斷睡眠

return schedule_timeout(timeout);

-》expire = timeout + jiffies; //計(jì)算到期時(shí)的jiffies值

timer.task = current; //記錄定時(shí)器到期要喚醒的任務(wù) 為當(dāng)前任務(wù)

timer_setup_on_stack(&timer.timer, process_timeout, 0); //初始化定時(shí)器 超時(shí)回調(diào)為process_timeout

__mod_timer(&timer.timer, expire, MOD_TIMER_NOTPENDING); //添加定時(shí)器

schedule(); //主動(dòng)調(diào)度

再看下超時(shí)回調(diào)為process_timeout:

process_timeout

-》struct process_timer *timeout = from_timer(timeout, t, timer); //通過定時(shí)器結(jié)構(gòu)獲得process_timer

wake_up_process(timeout-》task); //喚醒其管理的任務(wù)

可以看到,msleep實(shí)現(xiàn)睡眠也是通過定時(shí)器,首先設(shè)置當(dāng)前任務(wù)狀態(tài)為不可中斷睡眠,然后設(shè)置定時(shí)器超時(shí)時(shí)間為傳遞的ms級(jí)延遲轉(zhuǎn)換的jiffies,超時(shí)回調(diào)為process_timeout,然后將定時(shí)器添加到系統(tǒng)中,最后調(diào)用schedule發(fā)起主動(dòng)調(diào)度,當(dāng)定時(shí)器超時(shí)的時(shí)候調(diào)用process_timeout來喚醒睡眠的任務(wù)。

5.2 mutex鎖

mutex鎖是可睡眠鎖的一種,當(dāng)申請(qǐng)mutex鎖時(shí)發(fā)現(xiàn)其他內(nèi)核路徑已經(jīng)持有這把鎖,當(dāng)前任務(wù)就會(huì)睡眠等待在這把鎖上。

下面我們來看他的實(shí)現(xiàn),主要看睡眠的部分:

kernel/locking/mutex.c

mutex_lock

-》__mutex_lock_slowpath

-》__mutex_lock(lock, TASK_UNINTERRUPTIBLE, 0, NULL, _RET_IP_) //睡眠的狀態(tài)為不可中斷睡眠

-》__mutex_lock_common

-》

...

waiter.task = current; //記錄需要喚醒的任務(wù)為當(dāng)前任務(wù)

set_current_state(state); //設(shè)置睡眠狀態(tài)

for (;;) {

if (__mutex_trylock(lock)) //嘗試獲得鎖

goto acquired;

schedule_preempt_disabled();

-》schedule(); //主動(dòng)調(diào)度

}

acquired:

__set_current_state(TASK_RUNNING);//設(shè)置狀態(tài)為可運(yùn)行狀態(tài)

可以看到mutex鎖實(shí)現(xiàn)睡眠套路和之前是一樣的:申請(qǐng)mutex鎖的時(shí)候,如果其他內(nèi)核路徑已經(jīng)持有這把鎖,首先通過mutex鎖的相關(guān)結(jié)構(gòu)來記錄下當(dāng)前任務(wù),然后設(shè)置任務(wù)狀態(tài)為不可中斷睡眠,接著在一個(gè)for循環(huán)中調(diào)用schedule_preempt_disabled發(fā)生主動(dòng)調(diào)度,于是當(dāng)前任務(wù)就睡眠在這把鎖上。

當(dāng)其他內(nèi)核路徑釋放了這把鎖,就會(huì)喚醒等待在這把鎖上的任務(wù),當(dāng)前任務(wù)就獲得了這把鎖,然后進(jìn)入鎖的臨界區(qū),喚醒操作就完成了(關(guān)于喚醒的技術(shù)細(xì)節(jié),后面的喚醒專題會(huì)詳細(xì)講解)。

6.總結(jié)

進(jìn)程睡眠按照應(yīng)用場(chǎng)景可以分為:延遲睡眠和等待某些特定條件而睡眠,實(shí)際上都可以歸于等待某些特定條件而睡眠,因?yàn)檠舆t特定時(shí)間也可以作為特定條件。

進(jìn)程睡眠按照進(jìn)程所處的特權(quán)級(jí)別可以分為:用戶態(tài)進(jìn)程睡眠和內(nèi)核態(tài)進(jìn)程睡眠,用戶態(tài)進(jìn)程睡眠需要進(jìn)程通過系統(tǒng)調(diào)用陷入內(nèi)核來發(fā)起睡眠請(qǐng)求。對(duì)于進(jìn)程睡眠,內(nèi)核主要需要做三大步操作:

1.設(shè)置任務(wù)狀態(tài)為睡眠狀態(tài) 2.記錄睡眠的任務(wù) 3.發(fā)起主動(dòng)調(diào)度。這三大步操作都是非常有必要,第一步設(shè)置睡眠狀態(tài)為后面調(diào)用主調(diào)度器做必要的標(biāo)識(shí)準(zhǔn)備;第二步記錄下睡眠的任務(wù)是為了以后喚醒任務(wù)來準(zhǔn)備的;第三步是睡眠的主體部分,這里會(huì)將睡眠的任務(wù)從運(yùn)行隊(duì)列中踢出,選擇下一個(gè)任務(wù)運(yùn)行。

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

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

責(zé)任編輯:haq

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

    關(guān)注

    4

    文章

    1467

    瀏覽量

    42867
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11756

    瀏覽量

    219000

原文標(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)核的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    Linux 內(nèi)核的世界里,有一個(gè)默默工作的 "計(jì)時(shí)器"——jiffies。它不像我們手機(jī)上的時(shí)鐘那樣顯示年月日,卻掌控著內(nèi)核中絕大多數(shù)時(shí)間相關(guān)的操作:從進(jìn)程調(diào)度到設(shè)備驅(qū)動(dòng)的定時(shí)檢查,都離不開它的身影。
    的頭像 發(fā)表于 02-04 16:27 ?812次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>的“心跳”:jiffies如何為系統(tǒng)計(jì)時(shí)?

    深入RK3588內(nèi)核:rockchip_linux_defconfig的作用與調(diào)試價(jià)值

    在 RK3588 芯片的 Linux 開發(fā)中,有一個(gè)文件始終是開發(fā)者繞不開的核心 ——kernel/arch/arm64/configs/rockchip_linux_defconfig。無論是首次
    的頭像 發(fā)表于 02-03 15:56 ?1148次閱讀
    深入RK3588<b class='flag-5'>內(nèi)核</b>:rockchip_<b class='flag-5'>linux</b>_defconfig的作用與調(diào)試價(jià)值

    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ù)處理、容器化部署等場(chǎng)景下,合理的
    的頭像 發(fā)表于 01-28 14:27 ?418次閱讀

    【「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ǔ)

    ()、msleep_interruptible()這些API用于簡(jiǎn)單睡眠 內(nèi)核延遲或忙等待 可以調(diào)用ndelay()、udelay()、mdelay()這些API實(shí)現(xiàn) Linux內(nèi)核時(shí)
    發(fā)表于 01-12 22:45

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

    “處理內(nèi)核的核心輔助函數(shù)”進(jìn)行學(xué)習(xí)。 第3章又是以5個(gè)主題展開討論學(xué)習(xí),①、Linux內(nèi)核加鎖機(jī)制和共享資源;②、處理內(nèi)核等待、睡眠和延遲機(jī)
    發(fā)表于 01-10 22:08

    Linux內(nèi)核日志玩明白了嗎?printk調(diào)試神器全解析

    的日志等級(jí)機(jī)制,從參數(shù)配置到實(shí)戰(zhàn)用法一次講透~一、printk與printf的差異用戶態(tài)的printf大家都熟,直接打印內(nèi)容,簡(jiǎn)單粗暴。但內(nèi)核場(chǎng)景更復(fù)雜,系統(tǒng)崩潰或是
    的頭像 發(fā)表于 12-19 08:32 ?858次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內(nèi)核</b>日志玩明白了嗎?printk調(diào)試神器全解析

    探索操作系統(tǒng)底層的關(guān)鍵接口

      在linux中,將程序的運(yùn)行空間分為內(nèi)核空間與用戶空間(內(nèi)核態(tài)用戶
    的頭像 發(fā)表于 11-08 12:42 ?743次閱讀

    deepin亮相2025中國(guó)Linux內(nèi)核開發(fā)者大會(huì)

    11 月 1 日,第二十屆中國(guó) Linux 內(nèi)核開發(fā)者大會(huì)(CLK)在深圳舉辦。CLK 作為國(guó)內(nèi) Linux 內(nèi)核領(lǐng)域極具影響力的峰會(huì),由清華大學(xué)、Intel、華為、阿里云、富士通南大
    的頭像 發(fā)表于 11-05 17:59 ?814次閱讀

    深入了解系統(tǒng)調(diào)用API:探索操作系統(tǒng)底層的關(guān)鍵接口

    一、前言 為什么用戶程序不能直接訪問系統(tǒng)內(nèi)核模式提供的服務(wù)? 在linux中,將程序的運(yùn)行空間分為內(nèi)核空間與用戶空間(
    的頭像 發(fā)表于 11-03 09:20 ?695次閱讀

    求助,關(guān)于rt-smart用戶態(tài)線程實(shí)時(shí)性差的問題求解

    我在樹莓派4B上使用v5.2.0 開啟smart的rt-thread 并啟用SMP多核(4核)內(nèi)核時(shí),在用戶態(tài)內(nèi)核態(tài)運(yùn)行同樣的代碼測(cè)試:
    發(fā)表于 09-26 08:25

    Linux內(nèi)核參數(shù)調(diào)優(yōu)方案

    在高并發(fā)微服務(wù)環(huán)境中,網(wǎng)絡(luò)性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細(xì)化的Linux內(nèi)核參數(shù)調(diào)優(yōu),讓你的K8s節(jié)點(diǎn)網(wǎng)絡(luò)性能提升30%以上。
    的頭像 發(fā)表于 08-06 17:50 ?945次閱讀

    如何配置和驗(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 ?1147次閱讀

    樹莓派4 性能大比拼:標(biāo)準(zhǔn)Linux與實(shí)時(shí)Linux 4.19內(nèi)核的延遲測(cè)試

    引言本文是對(duì)我之前關(guān)于RaspberryPi3同一主題的帖子的更新。與之前的帖子一樣,我使用的是隨Raspbian鏡像提供的標(biāo)準(zhǔn)內(nèi)核,以及應(yīng)用了RT補(bǔ)丁的相似內(nèi)核版本。對(duì)于實(shí)時(shí)版,我
    的頭像 發(fā)表于 03-25 09:39 ?808次閱讀
    樹莓派4 性能大比拼:標(biāo)準(zhǔn)<b class='flag-5'>Linux</b>與實(shí)時(shí)<b class='flag-5'>Linux</b> 4.19<b class='flag-5'>內(nèi)核</b>的延遲測(cè)試

    飛凌嵌入式ElfBoard ELF 1板卡-內(nèi)核空間與用戶空間的數(shù)據(jù)拷貝之?dāng)?shù)據(jù)拷貝介紹

    Linux系統(tǒng)中,內(nèi)核空間和用戶空間是兩個(gè)獨(dú)立的地址空間,它們有不同的訪問權(quán)限和內(nèi)存保護(hù)機(jī)制。在內(nèi)核空間和用戶空間之間進(jìn)行數(shù)據(jù)傳輸時(shí),需要
    發(fā)表于 03-19 08:55