欧美一级特黄大片做受成人-亚洲成人一区二区电影-激情熟女一区二区三区-日韩专区欧美专区国产专区

Linux內(nèi)核態(tài)搶占怎么實(shí)現(xiàn)

本篇內(nèi)容介紹了“ Linux內(nèi)核態(tài)搶占怎么實(shí)現(xiàn)”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

成都創(chuàng)新互聯(lián)服務(wù)項(xiàng)目包括青岡網(wǎng)站建設(shè)、青岡網(wǎng)站制作、青岡網(wǎng)頁制作以及青岡網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,青岡網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到青岡省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!

1. 非搶占式和可搶占式內(nèi)核的區(qū)別

為了簡化問題,我使用嵌入式實(shí)時(shí)系統(tǒng)uC/OS作為例子。首先要指出的是,uC/OS只有內(nèi)核態(tài),沒有用戶態(tài),這和Linux不一樣。

多任務(wù)系統(tǒng)中,內(nèi)核負(fù)責(zé)管理各個(gè)任務(wù),或者說為每個(gè)任務(wù)分配CPU時(shí)間,并且負(fù)責(zé)任務(wù)之間的通訊。內(nèi)核提供的基本服務(wù)是任務(wù)切換。調(diào)度(Scheduler),英文還有一詞叫dispatcher,也是調(diào)度的意思。這是內(nèi)核的主要職責(zé)之一,就是要決定該輪到哪個(gè)任務(wù)運(yùn)行了。多數(shù)實(shí)時(shí)內(nèi)核是基于優(yōu)先級(jí)調(diào)度法的。每個(gè)任務(wù)根據(jù)其重要程度的不同被賦予一定的優(yōu)先級(jí)?;趦?yōu)先級(jí)的調(diào)度法指,CPU總是讓處在就緒態(tài)的優(yōu)先級(jí)***的任務(wù)先運(yùn)行。然而,究竟何時(shí)讓高優(yōu)先級(jí)任務(wù)掌握CPU的使用權(quán),有兩種不同的情況,這要看用的是什么類型的內(nèi)核,是不可剝奪型的還是可剝奪型內(nèi)核。

非搶占式內(nèi)核

非搶占式內(nèi)核是由任務(wù)主動(dòng)放棄CPU的使用權(quán)。非搶占式調(diào)度法也稱作合作型多任務(wù),各個(gè)任務(wù)彼此合作共享一個(gè)CPU。異步事件還是由中斷服務(wù)來處理。中斷服務(wù)可以使一個(gè)高優(yōu)先級(jí)的任務(wù)由掛起狀態(tài)變?yōu)榫途w狀態(tài)。但中斷服務(wù)以后控制權(quán)還是回到原來被中斷了的那個(gè)任務(wù),直到該任務(wù)主動(dòng)放棄CPU的使用權(quán)時(shí),那個(gè)高優(yōu)先級(jí)的任務(wù)才能獲得CPU的使用權(quán)。非搶占式內(nèi)核如下圖所示。

非搶占式內(nèi)核的優(yōu)點(diǎn)有:

  • 中斷響應(yīng)快(與搶占式內(nèi)核比較);

  • 允許使用不可重入函數(shù);

  • 幾乎不需要使用信號(hào)量保護(hù)共享數(shù)據(jù)。運(yùn)行的任務(wù)占有CPU,不必?fù)?dān)心被別的任務(wù)搶占。這不是絕對的,在打印機(jī)的使用上,仍需要滿足互斥條件。

非搶占式內(nèi)核的缺點(diǎn)有:

  • 任務(wù)響應(yīng)時(shí)間慢。高優(yōu)先級(jí)的任務(wù)已經(jīng)進(jìn)入就緒態(tài),但還不能運(yùn)行,要等到當(dāng)前運(yùn)行著的任務(wù)釋放CPU。

  • 非搶占式內(nèi)核的任務(wù)級(jí)響應(yīng)時(shí)間是不確定的,不知道什么時(shí)候***優(yōu)先級(jí)的任務(wù)才能拿到CPU的控制權(quán),完全取決于應(yīng)用程序什么時(shí)候釋放CPU。

搶占式內(nèi)核

使用搶占式內(nèi)核可以保證系統(tǒng)響應(yīng)時(shí)間。***優(yōu)先級(jí)的任務(wù)一旦就緒,總能得到CPU的使用權(quán)。當(dāng)一個(gè)運(yùn)行著的任務(wù)使一個(gè)比它優(yōu)先級(jí)高的任務(wù)進(jìn)入了就緒態(tài),當(dāng)前任務(wù)的CPU使用權(quán)就會(huì)被剝奪,或者說被掛起了,那個(gè)高優(yōu)先級(jí)的任務(wù)立刻得到了CPU的控制權(quán)。如果是中斷服務(wù)子程序使一個(gè)高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒態(tài),中斷完成時(shí),中斷了的任務(wù)被掛起,優(yōu)先級(jí)高的那個(gè)任務(wù)開始運(yùn)行。搶占式內(nèi)核如下圖所示。

搶占式內(nèi)核的優(yōu)點(diǎn)有:

  • 使用搶占式內(nèi)核,***優(yōu)先級(jí)的任務(wù)什么時(shí)候可以執(zhí)行,可以得到CPU的使用權(quán)是可知的。使用搶占式內(nèi)核使得任務(wù)級(jí)響應(yīng)時(shí)間得以***化。

搶占式內(nèi)核的缺點(diǎn)有:

  • 不能直接使用不可重入型函數(shù)。調(diào)用不可重入函數(shù)時(shí),要滿足互斥條件,這點(diǎn)可以使用互斥型信號(hào)量來實(shí)現(xiàn)。如果調(diào)用不可重入型函數(shù)時(shí),低優(yōu)先級(jí)的任務(wù)CPU的使用權(quán)被高優(yōu)先級(jí)任務(wù)剝奪,不可重入型函數(shù)中的數(shù)據(jù)有可能被破壞。

2. Linux下的用戶態(tài)搶占和內(nèi)核態(tài)搶占

Linux除了內(nèi)核態(tài)外還有用戶態(tài)。用戶程序的上下文屬于用戶態(tài),系統(tǒng)調(diào)用和中斷處理例程上下文屬于內(nèi)核態(tài)。在2.6 kernel以前,Linux  kernel只支持用戶態(tài)搶占。

2.1 用戶態(tài)搶占(User Preemption)

在kernel返回用戶態(tài)(user-space)時(shí),并且need_resched標(biāo)志為1時(shí),scheduler被調(diào)用,這就是用戶態(tài)搶占。當(dāng)kernel返回用戶態(tài)時(shí),系統(tǒng)可以安全的執(zhí)行當(dāng)前的任務(wù),或者切換到另外一個(gè)任務(wù)。當(dāng)中斷處理例程或者系統(tǒng)調(diào)用完成后,kernel返回用戶態(tài)時(shí),need_resched標(biāo)志的值會(huì)被檢查,假如它為1,調(diào)度器會(huì)選擇一個(gè)新的任務(wù)并執(zhí)行。

中斷和系統(tǒng)調(diào)用的返回路徑(return path)的實(shí)現(xiàn)在entry.S中(entry.S不僅包括kernel entry code,也包括kernel  exit code)。

2.2 內(nèi)核態(tài)搶占(Kernel Preemption)

在2.6 kernel以前,kernel code(中斷和系統(tǒng)調(diào)用屬于kernel  code)會(huì)一直運(yùn)行,直到code被完成或者被阻塞(系統(tǒng)調(diào)用可以被阻塞)。在 2.6 kernel里,Linux  kernel變成可搶占式。當(dāng)從中斷處理例程返回到內(nèi)核態(tài)(kernel-space)時(shí),kernel會(huì)檢查是否可以搶占和是否需要重新調(diào)度。kernel可以在任何時(shí)間點(diǎn)上搶占一個(gè)任務(wù)(因?yàn)橹袛嗫梢园l(fā)生在任何時(shí)間點(diǎn)上),只要在這個(gè)時(shí)間點(diǎn)上kernel的狀態(tài)是安全的、可重新調(diào)度的。

3. 內(nèi)核態(tài)搶占的設(shè)計(jì)

3.1 可搶占的條件

要滿足什么條件,kernel才可以搶占一個(gè)任務(wù)的內(nèi)核態(tài)呢?

  • 沒持有鎖。鎖是用于保護(hù)臨界區(qū)的,不能被搶占。

  • Kernel code可重入(reentrant)。因?yàn)閗ernel是SMP-safe的,所以滿足可重入性。

如何判斷當(dāng)前上下文(中斷處理例程、系統(tǒng)調(diào)用、內(nèi)核線程等)是沒持有鎖的?Linux在每個(gè)每個(gè)任務(wù)的thread_info結(jié)構(gòu)中增加了preempt_count變量作為preemption的計(jì)數(shù)器。這個(gè)變量初始為0,當(dāng)加鎖時(shí)計(jì)數(shù)器增一,當(dāng)解鎖時(shí)計(jì)數(shù)器減一。

3.2 內(nèi)核態(tài)需要搶占的觸發(fā)條件

內(nèi)核提供了一個(gè)need_resched標(biāo)志(這個(gè)標(biāo)志在任務(wù)結(jié)構(gòu)thread_info中)來表明是否需要重新執(zhí)行調(diào)度。

3.3 何時(shí)觸發(fā)重新調(diào)度

set_tsk_need_resched():設(shè)置指定進(jìn)程中的need_resched標(biāo)志

clear_tsk need_resched():清除指定進(jìn)程中的need_resched標(biāo)志

need_resched():檢查need_ resched標(biāo)志的值;如果被設(shè)置就返回真,否則返回假

什么時(shí)候需要重新調(diào)度:

  • 時(shí)鐘中斷處理例程檢查當(dāng)前任務(wù)的時(shí)間片,當(dāng)任務(wù)的時(shí)間片消耗完時(shí),scheduler_tick()函數(shù)就會(huì)設(shè)置need_resched標(biāo)志;

  • 信號(hào)量、等到隊(duì)列、completion等機(jī)制喚醒時(shí)都是基于waitqueue的,而waitqueue的喚醒函數(shù)為default_wake_function,其調(diào)用try_to_wake_up將被喚醒的任務(wù)更改為就緒狀態(tài)并設(shè)置need_resched標(biāo)志。

  • 設(shè)置用戶進(jìn)程的nice值時(shí),可能會(huì)使高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒狀態(tài);

  • 改變?nèi)蝿?wù)的優(yōu)先級(jí)時(shí),可能會(huì)使高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒狀態(tài);

  • 新建一個(gè)任務(wù)時(shí),可能會(huì)使高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒狀態(tài);

  • 對CPU(SMP)進(jìn)行負(fù)載均衡時(shí),當(dāng)前任務(wù)可能需要放到另外一個(gè)CPU上運(yùn)行;

3.4 搶占發(fā)生的時(shí)機(jī)(何時(shí)檢查可搶占條件)

  • 當(dāng)一個(gè)中斷處理例程退出,在返回到內(nèi)核態(tài)時(shí)(kernel-space)。這是隱式的調(diào)用schedule()函數(shù),當(dāng)前任務(wù)沒有主動(dòng)放棄CPU使用權(quán),而是被剝奪了CPU使用權(quán)。

  • 當(dāng)kernel code從不可搶占狀態(tài)變?yōu)榭蓳屨紶顟B(tài)時(shí)(preemptible  again)。也就是preempt_count從正整數(shù)變?yōu)?時(shí)。這也是隱式的調(diào)用schedule()函數(shù)。

  • 一個(gè)任務(wù)在內(nèi)核態(tài)中顯式的調(diào)用schedule()函數(shù)。任務(wù)主動(dòng)放棄CPU使用權(quán)。

  • 一個(gè)任務(wù)在內(nèi)核態(tài)中被阻塞,導(dǎo)致需要調(diào)用schedule()函數(shù)。任務(wù)主動(dòng)放棄CPU使用權(quán)。

3.5 禁用/使能可搶占條件的操作

對preempt_count操作的函數(shù)有add_preempt_count()、sub_preempt_count()、inc_preempt_count()、dec_preempt_count()。

使能可搶占條件的操作是preempt_enable(),它調(diào)用dec_preempt_count()函數(shù),然后再調(diào)用preempt_check_resched()函數(shù)去檢查是否需要重新調(diào)度。

禁用可搶占條件的操作是preempt_disable(),它調(diào)用inc_preempt_count()函數(shù)。

在內(nèi)核中有很多函數(shù)調(diào)用了preempt_enable()和preempt_disable()。比如spin_lock()函數(shù)調(diào)用了preempt_disable()函數(shù),spin_unlock()函數(shù)調(diào)用了preempt_enable()函數(shù)。

3.6 什么時(shí)候不允許搶占

preempt_count()函數(shù)用于獲取preempt_count的值,preemptible()用于判斷內(nèi)核是否可搶占。

有幾種情況Linux內(nèi)核不應(yīng)該被搶占,除此之外,Linux內(nèi)核在任意一點(diǎn)都可被搶占。這幾種情況是:

  • 內(nèi)核正進(jìn)行中斷處理。在Linux內(nèi)核中進(jìn)程不能搶占中斷(中斷只能被其他中斷中止、搶占,進(jìn)程不能中止、搶占中斷),在中斷例程中不允許進(jìn)行進(jìn)程調(diào)度。進(jìn)程調(diào)度函數(shù)schedule()會(huì)對此作出判斷,如果是在中斷中調(diào)用,會(huì)打印出錯(cuò)信息。

  • 內(nèi)核正在進(jìn)行中斷上下文的Bottom Half(中斷的下半部)處理。硬件中斷返回前會(huì)執(zhí)行軟中斷,此時(shí)仍然處于中斷上下文中。

  • 內(nèi)核的代碼段正持有spinlock自旋鎖、writelock/readlock讀寫鎖等鎖,處干這些鎖的保護(hù)狀態(tài)中。內(nèi)核中的這些鎖是為了在SMP系統(tǒng)中短時(shí)間內(nèi)保證不同CPU上運(yùn)行的進(jìn)程并發(fā)執(zhí)行的正確性。當(dāng)持有這些鎖時(shí),內(nèi)核不應(yīng)該被搶占,否則由于搶占將導(dǎo)致其他CPU長期不能獲得鎖而死等。

  • 內(nèi)核正在執(zhí)行調(diào)度程序Scheduler。搶占的原因就是為了進(jìn)行新的調(diào)度,沒有理由將調(diào)度程序搶占掉再運(yùn)行調(diào)度程序。

  • 內(nèi)核正在對每個(gè)CPU“私有”的數(shù)據(jù)結(jié)構(gòu)操作(Per-CPU date  structures)。在SMP中,對于per-CPU數(shù)據(jù)結(jié)構(gòu)未用spinlocks保護(hù),因?yàn)檫@些數(shù)據(jù)結(jié)構(gòu)隱含地被保護(hù)了(不同的CPU有不一樣的per-CPU數(shù)據(jù),其他CPU上運(yùn)行的進(jìn)程不會(huì)用到另一個(gè)CPU的per-CPU數(shù)據(jù))。但是如果允許搶占,但一個(gè)進(jìn)程被搶占后重新調(diào)度,有可能調(diào)度到其他的CPU上去,這時(shí)定義的Per-CPU變量就會(huì)有問題,這時(shí)應(yīng)禁搶占。

4. Linux內(nèi)核態(tài)搶占的實(shí)現(xiàn)

4.1 數(shù)據(jù)結(jié)構(gòu)

[cpp] view plain copy

struct thread_info {        struct task_struct  *task;      /* main task structure */        struct exec_domain  *exec_domain;   /* execution domain */        /**        * 如果有TIF_NEED_RESCHED標(biāo)志,則必須調(diào)用調(diào)度程序。        */        unsigned long       flags;      /* low level flags */        /**        * 線程標(biāo)志:        *     TS_USEDFPU:表示進(jìn)程在當(dāng)前執(zhí)行過程中,是否使用過FPU、MMX和XMM寄存器。        */        unsigned long       status;     /* thread-synchronous flags */        /**        * 可運(yùn)行進(jìn)程所在運(yùn)行隊(duì)列的CPU邏輯號(hào)。        */        __u32           cpu;        /* current CPU */        __s32           preempt_count; /* 0 => preemptable, <0 => BUG */           mm_segment_t        addr_limit; /* thread address space:                              0-0xBFFFFFFF for user-thead                              0-0xFFFFFFFF for kernel-thread                           */        struct restart_block    restart_block;            unsigned long           previous_esp;   /* ESP of the previous stack in case                              of nested (IRQ) stacks                           */        __u8            supervisor_stack[0];    };

4.2 代碼流程

禁用/使能可搶占條件的函數(shù)

[cpp] view plain copy

#ifdef CONFIG_DEBUG_PREEMPT      extern void fastcall add_preempt_count(int val);      extern void fastcall sub_preempt_count(int val);    #else    # define add_preempt_count(val) do { preempt_count() += (val); } while (0)    # define sub_preempt_count(val) do { preempt_count() -= (val); } while (0)    #endif        #define inc_preempt_count() add_preempt_count(1)    #define dec_preempt_count() sub_preempt_count(1)       /**    * 在thread_info描述符中選擇preempt_count字段    */    #define preempt_count() (current_thread_info()->preempt_count)       #ifdef CONFIG_PREEMPT       asmlinkage void preempt_schedule(void);        /**    * 使搶占計(jì)數(shù)加1    */    #define preempt_disable() \    do { \        inc_preempt_count(); \        barrier(); \    } while (0)       /**    * 使搶占計(jì)數(shù)減1    */    #define preempt_enable_no_resched() \    do { \        barrier(); \        dec_preempt_count(); \    } while (0)        #define preempt_check_resched() \    do { \        if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) \            preempt_schedule(); \    } while (0)        /**    * 使搶占計(jì)數(shù)減1,并在thread_info描述符的TIF_NEED_RESCHED標(biāo)志被置為1的情況下,調(diào)用preempt_schedule()    */    #define preempt_enable() \    do { \        preempt_enable_no_resched(); \        preempt_check_resched(); \    } while (0)        #else        #define preempt_disable()       do { } while (0)    #define preempt_enable_no_resched() do { } while (0)    #define preempt_enable()        do { } while (0)    #define preempt_check_resched()     do { } while (0)        #endif

設(shè)置need_resched標(biāo)志的函數(shù)

[cpp] view plain copy

static inline void set_tsk_need_resched(struct task_struct *tsk)    {        set_tsk_thread_flag(tsk,TIF_NEED_RESCHED);    }        static inline void clear_tsk_need_resched(struct task_struct *tsk)    {        clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED);    }

“ Linux內(nèi)核態(tài)搶占怎么實(shí)現(xiàn)”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

新聞名稱:Linux內(nèi)核態(tài)搶占怎么實(shí)現(xiàn)
文章轉(zhuǎn)載:http://aaarwkj.com/article24/igsoce.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司微信公眾號(hào)、網(wǎng)站改版、全網(wǎng)營銷推廣、小程序開發(fā)云服務(wù)器

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計(jì)公司
九九热视频这里是精品| 日本精品动漫一区二区三区| 精品熟女少妇av免费观看| 69精品一区二区蜜桃视频| 免费黄片视频大全在线播放| 亚洲男人天堂在线视频| 亚洲天堂av在线有码| 丁香六月综合激情啪啪啪| 少妇高潮视频在线观看| 日韩午夜免费一区二区蜜桃| 亚洲精品一区二区成人影院| 国产精品传媒在线视频| 内射小美女阴户毛片在线| 国产精品久久久在线视频| 少妇内射呻吟中文字幕视频| 久久久国产精品9999综合| 精品人妻av中文字幕乱| 国产午夜在线观看免费视频| 日韩av在线免费在线观看| 男女性生活视频成年人观看| 日韩欧美亚洲制服丝袜| 国产在线成年人免费观看| 日韩精品一区二区一牛| 国产精品一级在线播放| 韩国日本午夜福利在线| 久久精品国产亚洲熟女| 蜜臀av午夜福利在线| 亚洲精品一区二区三区色| 久久精品免费激情视频| 欧美日韩一区二区高清在线| 国产69精品久久一级| 91精品国产综合久久香蕉麻豆| 欧美成人一区二区三区片| 韩国三级网站在线观看视频| 蜜臀av网站在线播放| 在线观看中文字幕不卡二区| 蜜臀av免费在线观看| 免费观看在线黄色大片| 亚洲国产精品一区一区| 日韩av在线国产观看| 国产一区二区三区在线观看俏佳人|