国产精品久久久aaaa,日日干夜夜操天天插,亚洲乱熟女香蕉一区二区三区少妇,99精品国产高清一区二区三区,国产成人精品一区二区色戒,久久久国产精品成人免费,亚洲精品毛片久久久久,99久久婷婷国产综合精品电影,国产一区二区三区任你鲁

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Linux內核用戶態是如何睡眠的

B4Pb_gh_6fde77c ? 來源:Linux內核遠航者 ? 作者:Linux內核遠航者 ? 2021-08-16 15:06 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

4.用戶態睡眠

以sleep為例來說明任務在用戶態是如何睡眠的。

首先我們通過strace工具來看下其調用的系統調用:

$ strace sleep 1

...

close(3) = 0

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

close(1) = 0

...

可以發現sleep主要調用clock_nanosleep系統調用來進行睡眠(也就是說用戶態任務睡眠需要調用系統調用陷入內核)。

下面我們來研究下clock_nanosleep的實現(這里集中到睡眠的實現,先忽略掉定時器等諸多的技術細節):

kernel/time/posix-timers.c

SYSCALL_DEFINE4(clock_nanosleep

-》const struct k_clock *kc = clockid_to_kclock(which_clock); //根據時鐘類型得到內核時鐘結構

return kc-》nsleep(which_clock, flags, &t); //調用內核時鐘結構的nsleep回調

我們傳遞過來的時鐘類型為CLOCK_REALTIME,則調用鏈為:

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); //初始化高精度定時器

sl-》timer.function = hrtimer_wakeup; //設置超時回調函數

sl-》task = current;。//設置超時時要喚醒的任務

-》do_nanosleep //睡眠操作

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

kernel/time/hrtimer.c

do_nanosleep

-》

do {

set_current_state(TASK_INTERRUPTIBLE); //設置可中斷的睡眠狀態

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

if (likely(t-》task))

freezable_schedule(); //主動調度

hrtimer_cancel(&t-》timer);

mode = HRTIMER_MODE_ABS;

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

__set_current_state(TASK_RUNNING); //設置為可運行狀態

do_nanosleep函數是睡眠的核心實現:首先設置任務的狀態為可中斷的睡眠狀態,然后開啟了之前設置的高精度定時器,隨即調用freezable_schedule進行真正的睡眠。

來看下freezable_schedule:

//include/linux/freezer.h

freezable_schedule

-》schedule()

-》__schedule(false);

可以看到最終調用主調度器__schedule進行主動調度。

當任務睡眠完成,定時器超時,會調用之前在__hrtimer_init_sleeper設置的超時回調函數hrtimer_wakeup將睡眠的任務喚醒(關于進程喚醒在這里就不在贅述,在后面的進程喚醒專題文章在進行詳細解讀),然后就可以再次獲得處理器的使用權了。

總結:處于用戶態的任務,如果想要睡眠一段時間必須向內核請求服務(如調用clock_nanosleep系統調用),內核中會設置一個高精度定時器,來記錄要睡眠的任務,然后設置任務狀態為可中斷的睡眠狀態,緊接著發生主動調度,這樣任務就發生睡眠了。

5.內核態睡眠

當任務處于內核態時,有時候也需要睡眠一段時間,不像任務處于用戶態需要發生系統調用來請求內核進行睡眠,在內核態可以直接調用睡眠函數。當然,內核態中,睡眠有兩種場景:一種是睡眠特定的時間的延遲操作(喚醒條件為超時),一種是等待特定條件滿足(如IO讀寫完成,可睡眠的鎖被釋放等)。

下面分別以msleep和mutex鎖為例講解內核態睡眠:

5.1 msleep

msleep做ms級別的睡眠延遲。

//kernel/time/timer.c

void msleep(unsigned int msecs)

{

unsigned long timeout = msecs_to_jiffies(msecs) + 1; //ms時間轉換為jiffies

while (timeout)

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

}

下面看下schedule_timeout_uninterruptible:

這里涉及到一個重要數據結構process_timer

struct process_timer {

struct timer_list timer; //定時器結構

struct task_struct *task; //定時器到期要喚醒的任務

};

schedule_timeout_uninterruptible

-》 __set_current_state(TASK_UNINTERRUPTIBLE); //設置任務狀態為不可中斷睡眠

return schedule_timeout(timeout);

-》expire = timeout + jiffies; //計算到期時的jiffies值

timer.task = current; //記錄定時器到期要喚醒的任務 為當前任務

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

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

schedule(); //主動調度

再看下超時回調為process_timeout:

process_timeout

-》struct process_timer *timeout = from_timer(timeout, t, timer); //通過定時器結構獲得process_timer

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

可以看到,msleep實現睡眠也是通過定時器,首先設置當前任務狀態為不可中斷睡眠,然后設置定時器超時時間為傳遞的ms級延遲轉換的jiffies,超時回調為process_timeout,然后將定時器添加到系統中,最后調用schedule發起主動調度,當定時器超時的時候調用process_timeout來喚醒睡眠的任務。

5.2 mutex鎖

mutex鎖是可睡眠鎖的一種,當申請mutex鎖時發現其他內核路徑已經持有這把鎖,當前任務就會睡眠等待在這把鎖上。

下面我們來看他的實現,主要看睡眠的部分:

kernel/locking/mutex.c

mutex_lock

-》__mutex_lock_slowpath

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

-》__mutex_lock_common

-》

...

waiter.task = current; //記錄需要喚醒的任務為當前任務

set_current_state(state); //設置睡眠狀態

for (;;) {

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

goto acquired;

schedule_preempt_disabled();

-》schedule(); //主動調度

}

acquired:

__set_current_state(TASK_RUNNING);//設置狀態為可運行狀態

可以看到mutex鎖實現睡眠套路和之前是一樣的:申請mutex鎖的時候,如果其他內核路徑已經持有這把鎖,首先通過mutex鎖的相關結構來記錄下當前任務,然后設置任務狀態為不可中斷睡眠,接著在一個for循環中調用schedule_preempt_disabled發生主動調度,于是當前任務就睡眠在這把鎖上。

當其他內核路徑釋放了這把鎖,就會喚醒等待在這把鎖上的任務,當前任務就獲得了這把鎖,然后進入鎖的臨界區,喚醒操作就完成了(關于喚醒的技術細節,后面的喚醒專題會詳細講解)。

6.總結

進程睡眠按照應用場景可以分為:延遲睡眠和等待某些特定條件而睡眠,實際上都可以歸于等待某些特定條件而睡眠,因為延遲特定時間也可以作為特定條件。

進程睡眠按照進程所處的特權級別可以分為:用戶態進程睡眠和內核態進程睡眠,用戶態進程睡眠需要進程通過系統調用陷入內核來發起睡眠請求。對于進程睡眠,內核主要需要做三大步操作:

1.設置任務狀態為睡眠狀態 2.記錄睡眠的任務 3.發起主動調度。這三大步操作都是非常有必要,第一步設置睡眠狀態為后面調用主調度器做必要的標識準備;第二步記錄下睡眠的任務是為了以后喚醒任務來準備的;第三步是睡眠的主體部分,這里會將睡眠的任務從運行隊列中踢出,選擇下一個任務運行。

原文標題:深入理解Linux內核之進程睡眠(下)

文章出處:【微信公眾號:Linux閱碼場】歡迎添加關注!文章轉載請注明出處。

責任編輯:haq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 內核
    +關注

    關注

    4

    文章

    1467

    瀏覽量

    42870
  • Linux
    +關注

    關注

    88

    文章

    11758

    瀏覽量

    219006

原文標題:深入理解Linux內核之進程睡眠(下)

文章出處:【微信號:gh_6fde77c41971,微信公眾號:FPGA干貨】歡迎添加關注!文章轉載請注明出處。

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

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Linux內核的“心跳”:jiffies如何為系統計時?

    Linux 內核的世界里,有一個默默工作的 "計時器"——jiffies。它不像我們手機上的時鐘那樣顯示年月日,卻掌控著內核中絕大多數時間相關的操作:從進程調度到設備驅動的定時檢查,都離不開它的身影。
    的頭像 發表于 02-04 16:27 ?814次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>的“心跳”:jiffies如何為系統計時?

    深入RK3588內核:rockchip_linux_defconfig的作用與調試價值

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

    Linux系統內核參數調優實戰指南

    Linux 內核參數調優是系統性能優化的核心環節。隨著云原生架構的普及和硬件性能的飛速提升,默認的內核參數配置往往無法充分發揮系統潛力。在高并發 Web 服務、大數據處理、容器化部署等場景下,合理的
    的頭像 發表于 01-28 14:27 ?426次閱讀

    【「Linux 設備驅動開發(第 2 版)」閱讀體驗】+讀深入理解Linux內核內存分配

    每個內存地址是虛擬的,不是直接指向RAM中的任何地址。當用戶訪問內存中的存儲單元時,都會進行地址轉換以匹配相應的物理內存。書籍的第10章討論了五個主題,對Linux內核內存分配進行詳細講解。 接著
    發表于 01-16 20:05

    【「Linux 設備驅動開發(第 2 版)」閱讀體驗】Linux內核開發基礎

    ()、msleep_interruptible()這些API用于簡單睡眠 內核延遲或忙等待 可以調用ndelay()、udelay()、mdelay()這些API實現 Linux內核
    發表于 01-12 22:45

    【「Linux 設備驅動開發(第 2 版)」閱讀體驗】+讀內核處理的核心輔助函數

    “處理內核的核心輔助函數”進行學習。 第3章又是以5個主題展開討論學習,①、Linux內核加鎖機制和共享資源;②、處理內核等待、睡眠和延遲機
    發表于 01-10 22:08

    Linux內核日志玩明白了嗎?printk調試神器全解析

    的日志等級機制,從參數配置到實戰用法一次講透~一、printk與printf的差異用戶的printf大家都熟,直接打印內容,簡單粗暴。但內核場景更復雜,系統崩潰或是
    的頭像 發表于 12-19 08:32 ?860次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>內核</b>日志玩明白了嗎?printk調試神器全解析

    探索操作系統底層的關鍵接口

      在linux中,將程序的運行空間分為內核空間與用戶空間(內核用戶
    的頭像 發表于 11-08 12:42 ?743次閱讀

    deepin亮相2025中國Linux內核開發者大會

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

    深入了解系統調用API:探索操作系統底層的關鍵接口

    一、前言 為什么用戶程序不能直接訪問系統內核模式提供的服務? 在linux中,將程序的運行空間分為內核空間與用戶空間(
    的頭像 發表于 11-03 09:20 ?697次閱讀

    求助,關于rt-smart用戶線程實時性差的問題求解

    我在樹莓派4B上使用v5.2.0 開啟smart的rt-thread 并啟用SMP多核(4核)內核時,在用戶內核運行同樣的代碼測試:
    發表于 09-26 08:25

    Linux內核參數調優方案

    在高并發微服務環境中,網絡性能往往成為K8s集群的瓶頸。本文將深入探討如何通過精細化的Linux內核參數調優,讓你的K8s節點網絡性能提升30%以上。
    的頭像 發表于 08-06 17:50 ?947次閱讀

    如何配置和驗證Linux內核參數

    Linux系統運維和性能優化中,內核參數(sysctl)的配置至關重要。合理的參數調整可以顯著提升網絡性能、系統穩定性及資源利用率。然而,僅僅修改參數是不夠的,如何驗證這些參數是否生效同樣關鍵。
    的頭像 發表于 05-29 17:40 ?1150次閱讀

    樹莓派4 性能大比拼:標準Linux與實時Linux 4.19內核的延遲測試

    引言本文是對我之前關于RaspberryPi3同一主題的帖子的更新。與之前的帖子一樣,我使用的是隨Raspbian鏡像提供的標準內核,以及應用了RT補丁的相似內核版本。對于實時版,我
    的頭像 發表于 03-25 09:39 ?809次閱讀
    樹莓派4 性能大比拼:標準<b class='flag-5'>Linux</b>與實時<b class='flag-5'>Linux</b> 4.19<b class='flag-5'>內核</b>的延遲測試

    飛凌嵌入式ElfBoard ELF 1板卡-內核空間與用戶空間的數據拷貝之數據拷貝介紹

    Linux系統中,內核空間和用戶空間是兩個獨立的地址空間,它們有不同的訪問權限和內存保護機制。在內核空間和用戶空間之間進行數據傳輸時,需要
    發表于 03-19 08:55