溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何進(jìn)行l(wèi)inux0.11進(jìn)程睡眠喚醒的原理分析

發(fā)布時(shí)間:2021-12-03 15:20:34 來源:億速云 閱讀:217 作者:柒染 欄目:大數(shù)據(jù)

如何進(jìn)行l(wèi)inux0.11進(jìn)程睡眠喚醒的原理分析,針對(duì)這個(gè)問題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問題的小伙伴找到更簡(jiǎn)單易行的方法。

進(jìn)程的睡眠是通過調(diào)用sleep_on函數(shù),該函數(shù)修改了進(jìn)程的狀態(tài)并且通過schedule函數(shù)切換到其他進(jìn)程執(zhí)行,從而實(shí)現(xiàn)進(jìn)程的掛起,TASK_UNINTERRUPTIBLE狀態(tài)的進(jìn)程只能被wake_up函數(shù)喚醒。TASK_INTERRUPTIBLE狀態(tài)的進(jìn)程可以被wake_up和信號(hào)喚醒。喚醒的時(shí)候也是通過修改進(jìn)程的狀態(tài)為可運(yùn)行,然后等待下一次進(jìn)程調(diào)度,被喚醒的進(jìn)程不一定馬上得到執(zhí)行。

}
// 當(dāng)前進(jìn)程掛載到睡眠隊(duì)列p中,p指向隊(duì)列頭指針的地址
void sleep_on(struct task_struct **p)
{
    struct task_struct *tmp;

    if (!p)
        return;
    if (current == &(init_task.task))
        panic("task[0] trying to sleep");
    /*
        *p為第一個(gè)睡眠節(jié)點(diǎn)的地址,即tmp指向第一個(gè)睡眠節(jié)點(diǎn)
        頭指針指向當(dāng)前進(jìn)程,這個(gè)版本的實(shí)現(xiàn)沒有采用真正鏈表的形式,
        他通過每個(gè)進(jìn)程在棧中的臨時(shí)變量形成一個(gè)鏈表,每個(gè)睡眠的進(jìn)程,
        在棧里有一個(gè)變量指向后面一個(gè)睡眠節(jié)點(diǎn),然后把鏈表的頭指針指向當(dāng)前進(jìn)程,
        然后切換到其他進(jìn)程執(zhí)行,當(dāng)被wake_up喚醒的時(shí)候,wake_up會(huì)喚醒鏈表的第一個(gè)
        睡眠節(jié)點(diǎn),因?yàn)榈谝粋€(gè)節(jié)點(diǎn)里保存了后面一個(gè)節(jié)點(diǎn)的地址,所以他喚醒后面一個(gè)節(jié)點(diǎn),
        后面一個(gè)節(jié)點(diǎn)以此類推,從而把整個(gè)鏈表的節(jié)點(diǎn)喚醒,這里的實(shí)現(xiàn)類似nginx的filter,
        即每個(gè)模塊保存后面一個(gè)節(jié)點(diǎn)的地址,然后把全局指針指向自己。
    */
    tmp = *p;
    *p = current;
    // 不可中斷睡眠只能通過wake_up喚醒,即使有信號(hào)也無法喚醒
    current->state = TASK_UNINTERRUPTIBLE;
    schedule();
    // 喚醒后面一個(gè)節(jié)點(diǎn)
    if (tmp)
        tmp->state=0;
}

void interruptible_sleep_on(struct task_struct **p)
{
    struct task_struct *tmp;

    if (!p)
        return;
    if (current == &(init_task.task))
        panic("task[0] trying to sleep");
    tmp=*p;
    *p=current;
/*
    可中斷地睡眠,可以通過wake_up和接收信號(hào)喚醒,不可中斷的時(shí)候,
    能保證喚醒的時(shí)候,是從前往后逐個(gè)喚醒,但是可中斷睡眠無法保證這一點(diǎn),
    因?yàn)檫M(jìn)程可能被信號(hào)喚醒了,所以需要判斷全局指針是否指向了自己,即自己插入
    鏈表后,還有沒有進(jìn)程也插入了該鏈表
*/
repeat:    current->state = TASK_INTERRUPTIBLE;
    schedule();
    /*
        這里為true,說明是信號(hào)喚醒,因?yàn)閣ake_up能保證喚醒的是第一個(gè)節(jié)點(diǎn),
        這里先喚醒鏈表中比當(dāng)前進(jìn)程后插入鏈表的節(jié)點(diǎn),有點(diǎn)奇怪,自己被信號(hào)喚醒了,
        去喚醒別的進(jìn)程,自己卻還睡眠
    */
    if (*p && *p != current) {
        (**p).state=0;
        goto repeat;
    }
    // 類似sleep_on的原理
    *p=NULL;
    if (tmp)
        tmp->state=0;
}
// 喚醒隊(duì)列中的第一個(gè)節(jié)點(diǎn),并清空鏈表,因?yàn)榈谝粋€(gè)節(jié)點(diǎn)會(huì)向后喚醒其他節(jié)點(diǎn)
void wake_up(struct task_struct **p)
{
    if (p && *p) {
        (**p).state=0;
        *p=NULL;
    }
}

關(guān)于如何進(jìn)行l(wèi)inux0.11進(jìn)程睡眠喚醒的原理分析問題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI