



版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、Linux 內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)第二章Linux 內(nèi)核讀書筆記(1) 1-71 內(nèi)核開發(fā)特點(diǎn)1)內(nèi)核編譯時(shí)不能訪問C 庫;2)浮點(diǎn)數(shù)很難使用;3)內(nèi)核只有一個(gè)定長堆棧;4)注意同步和并發(fā)。第三章進(jìn)程管理1 current 宏:查找當(dāng)前運(yùn)行進(jìn)程的進(jìn)程描述符。2 進(jìn)程狀態(tài)( 5種)TASK_RUNNING: 1)正在運(yùn)行;2)在運(yùn)行隊(duì)列中等待執(zhí)行。TASK_INTERRUPTIBLE:進(jìn)程正在睡眠,可以被信號(hào)喚醒。TASK_UNINTERRUPTIBLE:進(jìn)程正在睡眠,不會(huì)收到信號(hào)被喚醒。TASK_ZOMBIE:僵死態(tài),進(jìn)程已經(jīng)結(jié)束,父進(jìn)程未使用wait4() 。TASK_STOPPED3 進(jìn)程上下文進(jìn)
2、程進(jìn)入內(nèi)核空間時(shí),current 宏依然有效,內(nèi)核“代表進(jìn)程執(zhí)行 ”。4 進(jìn)程創(chuàng)建1) fork() :拷貝當(dāng)前進(jìn)程創(chuàng)建一個(gè)子進(jìn)程。2) exec():讀取可執(zhí)行文件并載入地址空間開始運(yùn)行。3)寫時(shí)拷貝(copy-on-wrtie ):推遲數(shù)據(jù)拷貝,在需要寫入數(shù)據(jù)時(shí),數(shù)據(jù)才會(huì)被復(fù)制。4) vfork() :不拷貝父進(jìn)程的頁表項(xiàng),子進(jìn)程作為父進(jìn)程的一個(gè)線程在它的地址空間運(yùn)行,父進(jìn)程被阻塞直至子進(jìn)程退出,子進(jìn)程不能向地址塊空間寫入數(shù)據(jù)。5 線程Linux 把所有的線程都當(dāng)作進(jìn)程來實(shí)現(xiàn)。6 內(nèi)核線程: 獨(dú)立運(yùn)行在內(nèi)核中的標(biāo)準(zhǔn)進(jìn)程。 內(nèi)核線程沒有獨(dú)立的地址空間, 只能在內(nèi)核空間中運(yùn)行,創(chuàng)建內(nèi)核線程用
3、kernel_thread() 。7 進(jìn)程終結(jié)1)釋放資源;2)進(jìn)入 TASK_ZOMBIE ;3)等待 wait4() 。第四章進(jìn)程調(diào)度1 多任務(wù)系統(tǒng)非搶占式多任務(wù):主動(dòng)讓步搶占式多任務(wù)( preemptive ):時(shí)間片2 進(jìn)程IO 消耗型:常常阻塞處理器消耗型:執(zhí)行代碼3 動(dòng)態(tài)優(yōu)先級(jí)調(diào)度方法允許調(diào)度程序根據(jù)需要加減優(yōu)先級(jí)。兩組優(yōu)先級(jí)范圍:1) nice 值: -20至 +19,默認(rèn)值為 0, nice 值越大,優(yōu)先級(jí)越低。2)實(shí)時(shí)優(yōu)先級(jí):0至99,任何實(shí)時(shí)進(jìn)程優(yōu)先級(jí)都高于普通進(jìn)程。4 時(shí)間片默認(rèn)時(shí)間片為 20ms。進(jìn)程時(shí)間片用完 進(jìn)程到期 所有進(jìn)程都到期 重新計(jì)算時(shí)間片5 可執(zhí)行列隊(duì)(
4、runqueue):每個(gè)處理器一個(gè)的可執(zhí)行進(jìn)程鏈表,還包含每個(gè)處理器的調(diào)度信息。cpu_rq(processor):返回給定處理器的可執(zhí)行隊(duì)列指針。this_rq() :返回當(dāng)前處理器的可執(zhí)行隊(duì)列。task_rq(task):返回給定任務(wù)所在的隊(duì)列指針。this_rq_lock() :鎖住當(dāng)前可執(zhí)行列隊(duì)。rq_unlock() :釋放給定列隊(duì)上的鎖。為了避免死鎖,要鎖住多個(gè)運(yùn)行列隊(duì)的代碼,需要按同樣的順序獲得這些鎖。6 優(yōu)先級(jí)數(shù)組每個(gè)運(yùn)行列隊(duì)有兩個(gè)優(yōu)先級(jí)數(shù)組:一個(gè)活躍的,一個(gè)過期的。優(yōu)先級(jí)數(shù)組包含一個(gè)優(yōu)先級(jí)位圖,共有 140個(gè)優(yōu)先級(jí)用了 5個(gè) 32位長整形保存?;顒?dòng)數(shù)組:可執(zhí)行隊(duì)列上的進(jìn)程還有
5、時(shí)間片剩余。過期數(shù)組:可執(zhí)行隊(duì)列上的進(jìn)程耗盡了時(shí)間片。進(jìn)程從活動(dòng)數(shù)組移動(dòng)至過期數(shù)組時(shí)重新計(jì)算時(shí)間片。重新計(jì)算時(shí)間片,以靜態(tài)優(yōu)先級(jí)為基礎(chǔ)計(jì)算。為了判斷 Linux 進(jìn)程類型, Linux 記錄了進(jìn)程用于休眠和執(zhí)行的時(shí)間。若進(jìn)程交互性非常強(qiáng),時(shí)間片用完后,會(huì)被再次放入活動(dòng)數(shù)組。7 休眠休眠通過等待列隊(duì)進(jìn)程處理。等待列隊(duì): wait_queue_head_t靜態(tài)創(chuàng)建等待列隊(duì):DECLARE_W AITQUEUE動(dòng)態(tài)創(chuàng)建等待列隊(duì):init_waitqueue_head()加入等待列隊(duì):add_wait_queue()移出等待列隊(duì):remove_wait_queue()8 負(fù)載平衡保證可執(zhí)行列隊(duì)之間的負(fù)
6、載處于均衡狀態(tài)(用于SMP)。兩種調(diào)用方法:1)當(dāng)前可執(zhí)行列隊(duì)為空;2)系統(tǒng)定時(shí)器 200ms 一次。9 上下文切換1)將虛擬內(nèi)存從上一個(gè)進(jìn)程映射到新的進(jìn)程中;2)將上個(gè)進(jìn)程處理器的狀態(tài)切換到新的進(jìn)程,保存、恢復(fù)棧信息和寄存器信息。10 schedule()被調(diào)用的時(shí)間1)某個(gè)進(jìn)程耗盡時(shí)間片時(shí);2)優(yōu)先級(jí)高的進(jìn)程進(jìn)入可執(zhí)行態(tài)時(shí);3)返回用戶空間時(shí);4)中斷返回時(shí)。11 內(nèi)核搶占只要沒有持有鎖,內(nèi)核就可以進(jìn)行搶占。preempt_count計(jì)數(shù)器記錄內(nèi)核鎖的數(shù)量。內(nèi)核搶占時(shí)機(jī):1)從中斷返回內(nèi)核空間時(shí);2)當(dāng)內(nèi)核代碼再一次具有可搶占性的時(shí)候;3)內(nèi)核任務(wù)顯示調(diào)用shedule();4)內(nèi)核任務(wù)阻
7、塞。12 實(shí)時(shí)性內(nèi)核實(shí)時(shí)調(diào)度策略:1) SCHED_FIFO :簡單,先進(jìn)先出調(diào)度;2) SCHED_RR :時(shí)間片輪轉(zhuǎn)調(diào)度,耗盡時(shí)間片后不再執(zhí)行。 SCHED_NORMAL 是普通、非實(shí)時(shí)的調(diào)度策略。內(nèi)核實(shí)時(shí)調(diào)度策略是基于靜態(tài)優(yōu)先級(jí)的:內(nèi)核不為實(shí)時(shí)進(jìn)程計(jì)算動(dòng)態(tài)優(yōu)先級(jí),實(shí)時(shí)優(yōu)先級(jí)范圍: 0-99。動(dòng)態(tài)非實(shí)時(shí)優(yōu)先級(jí)范圍:100-139(對(duì)應(yīng) nice 值 -20至 +19)。第五章系統(tǒng)調(diào)用1 應(yīng)用程序通過軟中斷機(jī)制通知內(nèi)核。2 參數(shù)驗(yàn)證指針:1)指針指向的內(nèi)存區(qū)域?qū)儆谟脩艨臻g;2)指針指向的內(nèi)存區(qū)域?qū)儆诒具M(jìn)程地址空間;3)如果讀,內(nèi)存標(biāo)記為可讀;如果寫,內(nèi)存標(biāo)記為可寫。3 copy_to_use
8、r() 的三個(gè)參數(shù):1)進(jìn)程空間的目的地址內(nèi)存;2)內(nèi)核空間源地址;3)需要拷貝的數(shù)據(jù)長度(字節(jié)數(shù))。copybit_from_user() 和上面相反。第六章中斷和中斷處理程序1 上半部和下半部上半部:中斷處理程序下半部:稍后完成的工作2 注冊(cè)中斷int request_irq(irq, *handle, irqflag, *devname, *devid)irq中斷號(hào)。handle一個(gè)指針,指向中斷處理程序。irqflag標(biāo)志位: SA_INTERRUPT快速中斷處理程序(禁止其他中斷);SA_SHIRQ :可在多個(gè)中斷處理程序間共享中斷線。devnamedev_id與中斷相關(guān)的設(shè)備的AS
9、CII 文本表示法。用于共享中斷線,當(dāng)中斷需要退出時(shí),dev_id提供唯一的標(biāo)志信息。從共享中斷線的中斷處理程序中刪除指定程序。3 釋放中斷free_irq(unsigned int irq, void *dev_id)4 中斷處理程序irqreturn_t intr_handle(int irq, void *dev_id, struct pt_regs *regs)regs:一個(gè)指向結(jié)構(gòu)體的指針,包含中斷處理之前的處理器寄存器和狀態(tài),regs 使用越來越少,應(yīng)該忽略。返回值 irqreturn_t :1) IRQ_NONE :中斷對(duì)應(yīng)設(shè)備并不是注冊(cè)函數(shù)期間指定的產(chǎn)生源;2) IRQ_HAN
10、DLE :正常返回值。重入問題: Linux 的中斷處理程序無需考慮重入,當(dāng)一個(gè)給定的中斷處理程序正在執(zhí)行,相應(yīng)的中斷會(huì)被屏蔽。5 中斷上下文中斷上下文不可以睡眠,不能從中斷上下文中調(diào)用睡眠函數(shù)。中斷棧:現(xiàn)在中斷處理程序擁有自己的棧,每個(gè)處理器一個(gè),大小為4KB 。6 中斷控制local_irq_disable() :禁止當(dāng)前處理器上的本地中斷;local_irq_enable() :允許中斷;local_irq_save(flag) :禁止中斷并保存系統(tǒng)狀態(tài);local_irq_restore(flag) :恢復(fù)中斷并恢復(fù)到原來的狀態(tài);disable_irq(unsigned int irq
11、) :禁止指定中斷線;disable_irq_nosync() :不等待當(dāng)前中斷處理完畢就禁止指定中斷; enable_irq(unsigned int irq) :允許指定中斷;synchronize_irq() :等待一個(gè)特定的中斷處理程序的退出。如果調(diào)用了兩次disable_irq() ,需要對(duì)應(yīng)調(diào)用兩次enable_irq() 才可以恢復(fù)。第七章下半部和推后執(zhí)行的工作1 下半部1)縮短中斷執(zhí)行時(shí)間;2)下半部執(zhí)行時(shí)允許響應(yīng)所有的中斷。2 下半部的類型1) BH :早期實(shí)現(xiàn),現(xiàn)在已經(jīng)淘汰;2)任務(wù)列隊(duì)(task queue);3)軟中斷( softirq ):靜態(tài)定義的下半部接口,共32
12、個(gè),可在所有處理上同時(shí)執(zhí)行。4) tasklet:基于軟終端的動(dòng)態(tài)下半部實(shí)現(xiàn),不同類型的tasklet 可在不同處理器同時(shí)執(zhí)行,相同類型的tasklet 不可以同時(shí)執(zhí)行。5)工作列隊(duì)(work queue):取代任務(wù)列隊(duì),對(duì)推后執(zhí)行的工作排隊(duì)。6)內(nèi)核定時(shí)器:將操作推后到某個(gè)確定的時(shí)間段。3 軟中斷1)軟中斷最多有32個(gè)。2)一個(gè)軟中斷不會(huì)搶占另外一個(gè)軟中斷,唯一可以搶占軟中斷的是中斷處理程序。3)軟中斷的執(zhí)行時(shí)機(jī): ( 1)從一個(gè)硬件中斷代碼返回時(shí);( 2)在 ksoftirq 內(nèi)核線程中;( 3)顯示檢查和執(zhí)行處理的軟中斷代碼中,如網(wǎng)絡(luò)子系統(tǒng)。4)軟中斷保留給系統(tǒng)中對(duì)時(shí)間要求最嚴(yán)格和最重要
13、的下半部使用:如網(wǎng)絡(luò)和SCSI。4 tasklet1) tasklet 通過軟中斷實(shí)現(xiàn),本身也是軟中斷,有兩種:HI_SOFTIRQ (優(yōu)先級(jí)較高)和TASKLET_SOFTIRQ 。2)的狀態(tài)有:0、TASKLET_STATE_SCHED (已經(jīng)被調(diào)度,正等待運(yùn)行)和 TASKLET_STATE_RUN (正在運(yùn)行,應(yīng)用于多核系統(tǒng)) 。3) tasklet 的調(diào)度過程:( 1)檢查 tasklet 的狀態(tài)是否為 SCHED >返回;( 2)保存中斷,禁止本地中斷;( 3)將調(diào)度 tasklet 加入 tasklet_vec 或者 tasklet_hi_vec 表頭;( 4)喚起 TAS
14、KLET_SOFTIRQ 或 HI_SOFTIRQ 中斷 >do_softirq() ;( 5)恢復(fù)中斷并恢復(fù)原狀態(tài)。4)使用 tasklet( 1)聲明靜態(tài)創(chuàng)建DECLARE_TASKLETDECLARE_TASKLET_DISABLED動(dòng)態(tài)創(chuàng)建tasklet_init(t,tasklet_handle,dev)( 2) handlevoid tasklet_handle(unsigned long data) 由于 tasklet 靠軟中斷實(shí)現(xiàn),所以 tasklet 執(zhí)行中不能睡眠 >不能使用信號(hào)量或阻塞函數(shù)。tasklet 運(yùn)行時(shí)運(yùn)行中斷,需要做好保護(hù)工作。(3)調(diào)度task
15、let_schedule(&my_tasklet)加入調(diào)度列隊(duì)tasklet_disable() 禁止莫個(gè) tasklet,若正在執(zhí)行則等待執(zhí)行完畢再禁止 tasklet_disable_nosync() 立即禁止(不太安全) tasklet_enable() 激活一個(gè) tasklettasklet_kill()去掉列隊(duì)的第一個(gè)tasklet(4) ksoftirq輔助軟中斷內(nèi)核線程內(nèi)核不會(huì)立即處理重新觸發(fā)的軟中斷,當(dāng)大量軟中斷出現(xiàn)時(shí),內(nèi)核會(huì)喚起一組線程來處理這些負(fù)載。( nice=19)5 工作隊(duì)列( work queue )1)工作隊(duì)列可把工作推后,交由一個(gè)內(nèi)核線程去執(zhí)行。2)工作
16、隊(duì)列在進(jìn)程上下文執(zhí)行,允許重新調(diào)度甚至是睡眠,但無法訪問用戶空間。3)實(shí)現(xiàn)工作者線程events/n,n 是處理器編號(hào)。worker_thread() 函數(shù):執(zhí)行一個(gè)死循環(huán)并休眠,當(dāng)有操作,線程被喚醒。4)使用工作隊(duì)列( 1)聲明靜態(tài)創(chuàng)建DECLARE_WORK(name, void(*func)(void*), void *data)動(dòng)態(tài)創(chuàng)建INIT_WORK(struct work_struct *work, void (*func)(void*), void *data)(2)處理函數(shù)void work_handle(void *data)(3)調(diào)度shedule_work(&w
17、ork)馬上調(diào)度shedule_delayed_work(&work,delay)延時(shí)調(diào)度(4)刷新flush_scheduled_work(void)等待隊(duì)列中所有對(duì)象都被執(zhí)行后才返回。cancel_delayed_work(struct work_struct *work)取消延時(shí)的工作。(5)創(chuàng)建新的工作列隊(duì)可在默認(rèn)的工作列隊(duì)外創(chuàng)建新的進(jìn)程:creat_work(const char *name)queue_work()類似 schedule_work() ,針對(duì)自己的進(jìn)程。queue_delayed_work()flush_workqueue()6 下半部機(jī)制的選擇下半部上下文
18、順序執(zhí)行要求軟中斷中斷沒有tasklet中斷同類型不可以同時(shí)執(zhí)行工作隊(duì)列進(jìn)程沒有(和進(jìn)程上下文一樣被調(diào)度)1)易用性:工作列隊(duì)>tasklet> 軟中斷2)速度:軟中斷>tasklet> 工作隊(duì)列3)開銷:工作隊(duì)列>>tasklet 、軟中斷7 下半部的鎖機(jī)制1) tasklet( 1)相同類型的 tasklet 不允許同時(shí)執(zhí)行,無需同步。( 2)不同類型的 tasklet 需使用鎖機(jī)制。2)軟中斷所有共享數(shù)據(jù)結(jié)構(gòu)都需要合適的鎖。3)進(jìn)程上下文和下半部共享中斷,上下文訪問共享數(shù)據(jù)前,需禁止下半部并獲取鎖的使用權(quán)。4)中斷上下文和下半部共享中斷,需禁止中斷并取
19、得鎖使用權(quán)。local_bh_disable()禁止本地處理器的軟中斷和tasklet 處理 ,不用禁止工作列隊(duì)。local_bh_enable()Linux 內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)第八章內(nèi)核同步介紹讀書筆記(2) 8-101 臨界區(qū)和競爭條件臨界區(qū):訪問和操作共享數(shù)據(jù)的代碼段。競爭條件:兩個(gè)執(zhí)行線程處于同一個(gè)臨界區(qū)中。2 內(nèi)核中造成并發(fā)的原因1)中斷:任何時(shí)刻異步發(fā)生,打斷當(dāng)前執(zhí)行的代碼。2)軟中斷和tasklet:任何時(shí)刻喚醒或調(diào)度軟中斷、tasklet。3)內(nèi)核搶占(preempt)。4)睡眠及與用戶空間的同步:喚醒調(diào)度程序,調(diào)度新進(jìn)程執(zhí)行。5)對(duì)稱多處理器(SMP)。3 需要加速的代碼1)中斷
20、安全代碼;2) SMP 安全代碼;3)搶占安全代碼。給數(shù)據(jù)加鎖而不是給代碼加鎖。4 編程需注意的問題:1)數(shù)據(jù)是否全局?除了當(dāng)前線程,其他線程是否可以訪問?2)數(shù)據(jù)是否在進(jìn)程/中斷上下文中共享?是否在兩個(gè)不同中斷中共享?3)進(jìn)程在訪問數(shù)據(jù)時(shí)可否被搶占?被調(diào)度的新進(jìn)程是否會(huì)訪問同一數(shù)據(jù)?4)當(dāng)前進(jìn)程是否會(huì)睡眠(阻塞)在某些資源上?共享數(shù)據(jù)處于何種狀態(tài)?5)怎樣防止數(shù)據(jù)失控?若在另一處理器上調(diào)度?5 預(yù)防死鎖1) 加鎖順序是關(guān)鍵,使用嵌套鎖必須以相同順序獲取鎖;2)防止發(fā)生饑餓;3)不要重復(fù)請(qǐng)求同一個(gè)鎖;4)復(fù)雜的加鎖方案也可能造成死鎖 簡化設(shè)計(jì);5)建議以獲取鎖相反的順序來釋放鎖。第九章內(nèi)核同步
21、方法1 原子操作原子操作執(zhí)行過程不被打斷,原子操作接口分為整數(shù)操作接口和單獨(dú)位操作接口。2 原子整數(shù)操作只有 atomic_t 類型可用于整數(shù)原子操作。atomic_t 類型保證編譯器不對(duì)相應(yīng)的值進(jìn)行優(yōu)化。atomic_t 類型可以屏蔽不同體系結(jié)構(gòu)上實(shí)現(xiàn)原子類型的差異。atomic_t 類型只能使用24位(現(xiàn)在已經(jīng)沒有這個(gè)限制)。定義:asm/atomic.hatomic_t v;atomic_t u = ATOMIC_INIT(0);操作:atomic_set(&v, 4)atomic_add(z, &v)atomic_sub(int i, atomic *v)atomic_
22、inc(&v)atomic_dec(&v)atomic_read(&v)轉(zhuǎn)成整形atomic_dec_and_test(&v)給定原子變量減1,若為 0則返回真。3 原子位操作原子位操作對(duì)普通的內(nèi)存地址操作,沒有atomic_t類型。定義:asm/bitops.h操作:set_bit(int nr, void *addr)clear_bit(int nr, void *addr)change_bit(int nr, void *addr)翻轉(zhuǎn)test_and_set_bit() 設(shè)置并返回原先的值test_and_clear_bit()test_and_chan
23、ge()test_bit()返回第 nr 位非原子操作:_test_bit()4 自旋鎖自旋鎖最多只能被一個(gè)可執(zhí)行線程持有。若一個(gè)線程試圖獲得一個(gè)被征用的自旋鎖,線程會(huì)一直忙循環(huán) 選擇 等待鎖可用。缺點(diǎn):由于自旋鎖在等待時(shí)自旋(浪費(fèi)處理器時(shí)間),因此自旋鎖不應(yīng)長時(shí)間持有。優(yōu)點(diǎn):線程不用睡眠,不用進(jìn)行上下文切換。數(shù)據(jù)結(jié)構(gòu):結(jié)構(gòu)相關(guān)代碼:asm/spinlock.h接口定義:linux/spinlock.h聲明:spinlock_t mr_lock = SPIN_LOCK_UNLOCKED加鎖:spin_lock(&mr_lock)解鎖:spin_unlock(&mr_lock)自
24、旋鎖特點(diǎn):自旋鎖最多被一個(gè)線程持有,為SMP 提供了并發(fā)保護(hù)機(jī)制。單處理器編程時(shí)并不會(huì)加入自旋鎖,僅當(dāng)做檢測(cè)內(nèi)核搶占的開關(guān)。如果禁止內(nèi)核搶占,則自旋鎖無效。自旋鎖可用于中斷處理程序中 (信號(hào)量不可用于自旋鎖, 會(huì)自旋),中斷中使用自旋鎖首先應(yīng)當(dāng)關(guān)中斷。自旋鎖不可遞歸。自旋鎖操作:spin_lock_irqsave(&mr_lock, flag)spin_unlock_irqstore(&mr_lock, flag)保存中斷當(dāng)前狀態(tài),關(guān)中斷,獲取鎖恢復(fù)中斷到加鎖前狀態(tài)并釋放鎖spin_lock_irq(&mr_lock)關(guān)中斷,獲取鎖spin_unlock_irq(&am
25、p;mr_lock)關(guān)中斷,釋放鎖因?yàn)楹茈y搞清楚中斷情況,推薦使用前者。其他操作:spin_lock_init()動(dòng)態(tài)初始化知道spinlock_tspin_trylock()試圖獲取指定鎖,若未獲取則返回非0spin_is_locked()如制定鎖當(dāng)前正在被獲取,則返回非04 讀寫自旋鎖讀寫不同鎖,多人和可并發(fā)持有讀者鎖,寫鎖只能被一個(gè)任務(wù)持有。用法:rwlock_t mr_rwlock = RW_LOCK_UNLOCKED;read_lock(&mr_rwlock)read_unlock(&mr_rwlock)write_lock(&mr_rwlock)write_
26、unlock(&mr_rwlock)注意:( 1)不可將讀鎖 “升級(jí) ”為寫鎖,寫鎖會(huì)等待讀鎖。( 2)多個(gè)讀者可以安全獲得同一個(gè)讀鎖,也可遞歸獲取讀鎖。5 信號(hào)量1)信號(hào)量的特點(diǎn)( 1) Linux 中的信號(hào)量是一種睡眠鎖;( 2)信號(hào)量適用于鎖會(huì)被長期占有的情況;( 3)由于信號(hào)量會(huì)睡眠,所以只能用于進(jìn)程上下文中,中斷上下文不支持調(diào)度;( 4)可以在持有信號(hào)量時(shí)睡眠;( 5)不可以在持有信號(hào)量時(shí)使用自旋鎖;( 6)信號(hào)量允許任意數(shù)目的鎖持有者,自旋鎖一個(gè)時(shí)刻只允許一個(gè)任務(wù)持有;( 7)在聲明時(shí)課指定信號(hào)量擁有的持有者數(shù)量。2)創(chuàng)建信號(hào)量定義:asm/semaphore.h靜態(tài)聲明:
27、static DECLARE_SEMAPHORE_GENEIC(none互斥信號(hào)量聲明:static DECLARE_MUTEX(name)動(dòng)態(tài)創(chuàng)建:sema_init(sem, count)動(dòng)態(tài)創(chuàng)建互斥對(duì)象:init_MUTEX(sem)(注意大小寫)3)使用信號(hào)量,count)down()信號(hào)計(jì)數(shù)減 1,若為 0或大于 0,則獲取信號(hào)量,若為負(fù)數(shù),則任務(wù)等待。up()信號(hào)計(jì)數(shù)加 1,若等待隊(duì)列不為空,喚醒等待任務(wù)。down_interruptible(struct semaphore*)若信號(hào)量已被征用,則可進(jìn)入中斷睡眠狀態(tài)。down_trylock()試圖獲取信號(hào)量,若已被征用,則立刻返
28、回非零值。6 讀 -寫信號(hào)量(都是互斥信號(hào)量)定義: linux/rwsem.h靜態(tài)聲明:static DECLARE_RWSEM(name)動(dòng)態(tài)創(chuàng)建:init_rwsem(struct rw_semaphore *sem)功能:down_read()up_read()down_write()up_write()downgrade_writer()動(dòng)態(tài)將寫鎖轉(zhuǎn)換為讀鎖7 自旋鎖與信號(hào)量中斷上下文中只能使用自旋鎖。任務(wù)睡眠時(shí)只能使用信號(hào)量。需求 建議低開銷加鎖 優(yōu)先使用自旋鎖短期鎖定 優(yōu)先使用自旋鎖長期加鎖 優(yōu)先使用信號(hào)量中斷上下文加鎖 使用自旋鎖持有鎖需要睡眠 使用信號(hào)量8 完成變量完成變量是
29、同步兩個(gè)任務(wù)的一種簡單方法。定義: linux/completion.h靜態(tài)創(chuàng)建:DECLARE_COMPLETION(mr_comp)動(dòng)態(tài)創(chuàng)建:init_completion()方法:wait_for_completion(struct completion *)等待指定的完成變量接受信號(hào)complete(struct completion*)發(fā)信號(hào)喚醒等待任務(wù)9 禁止搶占內(nèi)核代碼使用自旋鎖作為非搶占區(qū)域的標(biāo)記。preempt_disable() 增加搶占計(jì)數(shù)值,從而禁止內(nèi)核搶占preempt_enable() 減少搶占計(jì)數(shù)值,當(dāng)減為0時(shí)檢查和執(zhí)行被掛起的任務(wù)preempt_enable_n
30、o_resched()preempt_count() 返回?fù)屨加?jì)數(shù)get_cpu()put_cpu()10 順序和屏障屏障( barrier ):確保城鄉(xiāng)運(yùn)行順序的指令。rmb() 阻止跨越屏障的轉(zhuǎn)入動(dòng)作發(fā)生重排序。read_barrier_depends() 阻止跨越屏障的具有數(shù)據(jù)依賴關(guān)系的載入動(dòng)作重排序。wmb() 阻止跨越屏障的載入和存儲(chǔ)動(dòng)作發(fā)生重排序。mb() 阻止跨越屏障的載入和存儲(chǔ)動(dòng)作發(fā)生重排序。smp_rmb() 在 SMP 上提供 rmb()功能,在UP 上提供 barrier() 功能。smp_read_barrier_depends()smp_wmb()smp_mb()ba
31、rrirer()阻止編譯器跨越屏障對(duì)載入或存儲(chǔ)操作進(jìn)行優(yōu)化。第十章定時(shí)器和時(shí)間管理1 時(shí)鐘中斷的工作1)跟新系統(tǒng)運(yùn)行時(shí)間;2)跟新實(shí)際時(shí)間;3)在 SMP 系統(tǒng)中均衡調(diào)度各處理器的運(yùn)行列隊(duì);4)檢查當(dāng)前進(jìn)程是否耗盡時(shí)間片,若耗盡則進(jìn)行重新調(diào)度;5)運(yùn)行超時(shí)的動(dòng)態(tài)定時(shí)器;6)更新資源消耗和處理器時(shí)間的統(tǒng)計(jì)值。2 節(jié)拍率HZARM100( 10ms)i386 1000 ( 1ms)x86-64提高 HZ 的優(yōu)點(diǎn):1)更高時(shí)鐘中斷解析度;2)提高時(shí)間驅(qū)動(dòng)事件的準(zhǔn)確性(平均誤差5ms->0.5ms);3)內(nèi)核定時(shí)器能夠以更高的頻度和更高準(zhǔn)確度執(zhí)行;4)依賴定時(shí)器的系統(tǒng)調(diào)用(如poll 和 sel
32、ect)能以更高精度運(yùn)行;5)對(duì)資源消耗和系統(tǒng)運(yùn)行時(shí)間的測(cè)量更準(zhǔn)確;6)提供進(jìn)程搶占的準(zhǔn)確度。缺點(diǎn):1)系統(tǒng)負(fù)擔(dān)增加;2)中斷占用處理器的時(shí)間增加。3 jifiesjiffies 全局變量用來記錄系統(tǒng)自啟動(dòng)以來產(chǎn)生的節(jié)拍總數(shù)。定義:linux/jiffies.hextern unsigned long volatile jiffies;extern u64 jiffies_64;jiffies 取 jifies_64 的低 32位jiffies 溢出回繞:#define time_after(unknown, known) (long)(known)-(long)(unknown)<0)
33、#define time_before(unknown, known) (long)(unknown)-(long)(known)<0)4 時(shí)間中斷處理程序流程:1)獲得鎖xtime_lock ;2)需要時(shí)應(yīng)答或重設(shè)系統(tǒng)時(shí)鐘;3)周期性使用墻上時(shí)間(實(shí)際時(shí)間)更新實(shí)時(shí)時(shí)鐘;4)調(diào)用架構(gòu)無關(guān)的do_timer() 函數(shù);( 1)增加 jiffies ;( 2)更新資源消耗的統(tǒng)計(jì)值;( 3)執(zhí)行到期的動(dòng)態(tài)定時(shí)器;( 4)執(zhí)行 schedule_tick() ;( 5)更新墻上時(shí)間 ->存有 xtime 中;( 6)計(jì)算平均負(fù)載。5 實(shí)際時(shí)間(墻上時(shí)間)定義 ; kernel/timer
34、.cstruct timespec xtime;struct timespec time_t tv_sec; / 秒,自 1970.7.1開始的秒數(shù)long tv_nsec; / 納秒,自上一秒開始的納秒數(shù)讀寫 xtime 需要用 xtime_lock用戶空間獲取墻上時(shí)間的接口:內(nèi)核空間獲取墻上時(shí)間的接口:鎖,是一個(gè)seqlock 鎖。gettimeofday()sys_gettimeofday() <- 系統(tǒng)調(diào)用設(shè)置當(dāng)前時(shí)間接口:settimeofday()6 定時(shí)器(動(dòng)態(tài)定時(shí)器)定義: linux/timer.hstruct time_list my_timer初始化:init_ti
35、mer(&my_timer);my_timer.expires = jiffies + delay;my_timer.data = 0;my_timer.function = my_function;處理函數(shù)格式:void my_function(unsigned long data)激活:add_timer(&my_timer)修改定時(shí)時(shí)間:mod_timer(&my_timer, jiffies+delay)停止定時(shí)器:del_timer(&my_timer)del_timer_sync() <- 用于 SMP,不可用戶中斷上下文7 延遲執(zhí)行1)忙等待
36、unsigned long delay = jiffies + delays;while(time_before(jiffies, delay);2)代碼等待時(shí)允許內(nèi)核重新調(diào)度其他任務(wù)unsigned long delay = jiffies + delays;while(time_before(jiffies, delay)cond_resched();延遲執(zhí)行在任何情況下都不應(yīng)該在持有鎖或禁止中斷時(shí)發(fā)生。jiffies 采用 volatile 型,每次循環(huán)都會(huì)從內(nèi)存中讀取。3)短延遲linux/delay.hvoid udelay(unsigned long usecs);void mde
37、lay(unsigned long msecs);短延時(shí)是通過循環(huán)實(shí)現(xiàn)的。BogoMips 不是為了表現(xiàn)機(jī)器性能,而是同udelay 和mdelay 使用。4) schedule_timeout()將需要延遲的任務(wù)睡眠至延遲時(shí)間耗盡(不能保證時(shí)間準(zhǔn)確,因?yàn)闀?huì)重新調(diào)度)使用:。set_current_state(TASK_INTERRUPTIBLE);schedule_timeout(X*HZ);使用場(chǎng)合為進(jìn)程上下文且不能持有鎖。Linux 內(nèi)核設(shè)計(jì)與實(shí)現(xiàn)讀書筆記 (3) 11-20第十一章內(nèi)存管理1 頁物理也是內(nèi)存管理的基本單位。定義:linux/mm.hstruct page page_fl
38、ag_t flags;/頁的狀態(tài)(臟、鎖定)atomic_t _count;/ 頁的引用記錄(0:內(nèi)核沒有引用,可用于新分配)atomic_t _mapcount;unsigned long private;/ 頁作為私有數(shù)據(jù)時(shí)使用struct address_space *mapping;/頁作為頁緩存時(shí)使用pgoff_tindex;struct list_head lru;void*virtual;/ 虛擬地址2 區(qū)( zone)ZONE_DMA :包含的頁用來執(zhí)行DMA 操作。ZONE_NORMAL:正常映射的頁。ZONE_HIGHMEM: “高端內(nèi)存 ”(并不能永久映射到內(nèi)核地址空間)
39、。3 獲得頁(獲取頁的接口)1) sttuct page* alloc_pages(unsigned int gfp_mask, unsigned int order)分配 2x 個(gè)連續(xù)物理頁,并返回指向第一個(gè)頁結(jié)構(gòu)體的指針。2) void* page_address(struct page * page)返回給定物理頁的邏輯地址。3) unsigned long _get_free_pages(unsigned int gft_mask, unsigned int order)與 alloc_page()相同,但直接返回第一頁的物理地址。4) struct page* alloc_page(
40、gfp_mask)unsigned long _get_free_page()以上兩個(gè)函數(shù)只分配一頁。5) unsigned long get_zeroed_page(gfp_mask)只分配一頁,且內(nèi)容填充0,返回邏輯地址指針。釋放頁:void _free_pages(struct page *page, unsigned int order);void free_pages(unsigned long addr, unsigned int order);void free_page(unsigned long addr);獲取頁后注意進(jìn)行錯(cuò)誤檢查。4 kmalloc()定義:linux/s
41、lab.hvoid* kmalloc(size_t, int flags)分配的內(nèi)存在物理上是連續(xù)的。最大能分配 128KB 。必須檢查分配是否成功。kfree() 和 kmalloc() 對(duì)應(yīng)void kfree(const void *ptr);5 gfp_mask 標(biāo)志該標(biāo)志可以分為三類:( 1)行為修飾符:描述內(nèi)核如何分配所需內(nèi)存。( 2)區(qū)修飾符:從哪個(gè)區(qū)分配內(nèi)存。( 3)類型:組合了行為和區(qū)修飾符,提供了常用的標(biāo)志。類型標(biāo)志:(1)GFP_ATOMIC分配高級(jí)、 優(yōu)先,用于中斷、 下半部、 鎖中及其他不能睡眠的情況配成功率較低) 。(分( 2) GFP_NOIO 分配可阻塞,不會(huì)啟
42、動(dòng)磁盤IO 。( 3) GFP_NOFS 分配可阻塞,可能啟動(dòng)磁盤IO,不會(huì)啟動(dòng)文件系統(tǒng)。(4) GFP_KERNEL最常使用,可阻塞。睡眠安全時(shí)用于進(jìn)程上下文(沒有鎖的情況)。( 5) GFP_USER 常規(guī)分配方式,可阻塞,用于為用戶空間分配內(nèi)存。( 6) GFP_HIGHUSER 從 ZONE_HIGHMEM 分配可阻塞,用于為用戶空間分配內(nèi)存。( 7) GFP_DMA 從 ZONE_DMA 分配內(nèi)存6 vmallc()分配內(nèi)存,虛擬地址連續(xù),物理地址不一定連續(xù)(類似malloc )。vmalloc() 為了把物理上不連續(xù)的頁轉(zhuǎn)換為虛擬地址連續(xù)的頁,需要專門建立頁表項(xiàng)。通過 vmallo
43、c() 獲得的頁必須一個(gè)一個(gè)進(jìn)行映射,導(dǎo)致 TLB 抖動(dòng)增大,因此僅在不得已情況下調(diào)用,且可能睡眠,不能用于中斷上下文。7 slab 分配器slab分配器把不同對(duì)象劃分為不同的高速緩存組,如進(jìn)程描述符組、索引節(jié)點(diǎn)組、kmalloc組等等。高速緩存又被劃分為不同的slba, slab 由一個(gè)或多個(gè)物理連續(xù)的頁組成(一般一頁)。slab 的狀態(tài)分為:滿、部分滿和空。高速緩存的數(shù)據(jù)結(jié)構(gòu)kmem_cache_t 保存著三個(gè)鏈表: slabs_full 、slabs_partial 和 slabs_empty。8 slab 分配器接口1)創(chuàng)建kmem_cache_t * kmem_cache_creat
44、(const char* name, size_t size, size_t align, unsigned long flags,void (*ctor)(void*, kmem_cache_t *, unsigned long), void (*dtor)(void*, kmem_cache_t *, unsigned long)(構(gòu)造)(析構(gòu))2)銷毀int kmem_cache_destroy(kmem_cache_t *cachep)3)從高速緩沖中獲取對(duì)象void* kmem_cache_alloc(kmem_chache_t *cachep, int flags)4)釋放一個(gè)對(duì)象
45、void kmem_cache_free(kmem_cache_t *cachep, void *objp)9 高端內(nèi)存X86 中,高于 896MB 的內(nèi)存是高端內(nèi)存,不能永久映射到內(nèi)核空間。永久映射:映射一個(gè)給定的page 結(jié)構(gòu)體到內(nèi)核地址空間void* kmap(struct page *page)低端內(nèi)存: 返回虛擬地址; 高端內(nèi)存: 建立永久映射再返回。void kunmap(struct page *page)臨時(shí)映射(原子映射) :當(dāng)上下文不能睡眠時(shí),可使用臨時(shí)映射(可用于中斷)void* kmap_atomic(struct page *page , enum km_type t
46、ype)void kunmap_atomic(void *kvaddr, enum km_type type)第十二章虛擬文件系統(tǒng)1 Unix文件系統(tǒng)四要素:文件、目錄、索引節(jié)點(diǎn)(inode)、安裝點(diǎn)(mount point )索引結(jié)點(diǎn):存儲(chǔ)訪問權(quán)限、大小、擁有者、創(chuàng)建時(shí)間等信息。超級(jí)塊:存儲(chǔ)文件系統(tǒng)的控制信息。2 VFS 對(duì)象1)超級(jí)塊對(duì)象:代表一個(gè)已安裝的文件系統(tǒng)。2)索引節(jié)點(diǎn)對(duì)象:代表一個(gè)文件。3)目錄項(xiàng)對(duì)象:代表一個(gè)目錄項(xiàng),是路徑的一個(gè)組成部分。4)文件對(duì)象:代表由進(jìn)程打開的文件。VFS 將目錄作為文件來處理,目錄項(xiàng)不同于目錄。3 超級(jí)塊對(duì)象各種文件系統(tǒng)必須實(shí)現(xiàn)超級(jí)塊,用于存儲(chǔ)指定文件
47、系統(tǒng)信息。超級(jí)塊通常存放于磁盤的特定扇區(qū)中。對(duì)于 sysfs 等非磁盤文件系統(tǒng),超級(jí)塊存在內(nèi)存中。4 索引節(jié)點(diǎn)對(duì)象索引節(jié)點(diǎn)對(duì)象包含內(nèi)核在操作文件或目錄時(shí)需要的全部信息。沒有索引節(jié)點(diǎn)的文件系統(tǒng),內(nèi)核需要建立這些信息。一個(gè)索引節(jié)點(diǎn)代表文件系統(tǒng)中的一個(gè)文件(包括設(shè)備、管道等特殊文件)。5 目錄項(xiàng)對(duì)象(dentry)路徑中的每個(gè)組成部分都由一個(gè)索引節(jié)點(diǎn)對(duì)象表示。目錄項(xiàng):每個(gè)目錄項(xiàng)代表一個(gè)目錄中的一個(gè)組成部分。eg: /bin/vi“ / ”“ 是bin三”“個(gè)目錄vi項(xiàng)”目錄項(xiàng)不保存在磁盤上,VFS 根據(jù)路徑現(xiàn)場(chǎng)創(chuàng)建。目錄項(xiàng)的狀態(tài):(1)被使用:對(duì)應(yīng)一個(gè)有效的inode,且對(duì)象存在使用者;(2)未使用
48、:對(duì)應(yīng)一個(gè)有效的inode, VFS 當(dāng)前未使用;( 3)負(fù),沒有對(duì)應(yīng)的有效索引節(jié)點(diǎn)。目錄項(xiàng)緩存:( 1) “被使用的 ”目錄項(xiàng)鏈表;( 2) “最近被使用 ”的雙向鏈表;( 3)散列表及散列函數(shù)。6 文件對(duì)象表示進(jìn)程已打開的文件,是打開文件在內(nèi)存中的表示。文件對(duì)象在內(nèi)存中,也沒有對(duì)應(yīng)的磁盤數(shù)據(jù)。第十三章塊 IO 層1 各種設(shè)備塊設(shè)備:隨機(jī)訪問固定大小數(shù)據(jù)片的設(shè)備。字符設(shè)備:按字符流方式有序被訪問,和塊設(shè)備的區(qū)別在于隨機(jī)訪問。扇區(qū):物理設(shè)備的最小可尋址單元(物理屬性) 。塊:文件系統(tǒng)的最小邏輯可尋址單元。2 IO 調(diào)度程序內(nèi)核會(huì)針對(duì)IO 操作進(jìn)行合并、排序預(yù)操作。Linux 電梯調(diào)度算法(2.
49、4內(nèi)核中的舊算法) :( 1)相鄰合并;( 2)駐留時(shí)間過長的請(qǐng)求放入隊(duì)列尾部;( 3)保證扇區(qū)的磁盤訪問順序;( 4)不合適的請(qǐng)求插入位置被放入列隊(duì)尾部。新的調(diào)度算法:(1)最后期限IO 調(diào)度,每個(gè)請(qǐng)求都有一個(gè)超時(shí)時(shí)間,讀默認(rèn)500ms,寫默認(rèn) 5s。( 2)預(yù)測(cè) IO 調(diào)度,保持良好的讀響應(yīng),同時(shí)提供良好的全局吞吐率。( 3)完全公正的排隊(duì) IO 調(diào)度程序( CFQ), IO 進(jìn)程列隊(duì)采用時(shí)間片輪轉(zhuǎn)。(4)空操作IO 調(diào)度程序,不進(jìn)行排序,只進(jìn)行合并,適用于閃存等無需“尋道 ”的介質(zhì)。第十四章進(jìn)程地址空間1 內(nèi)存區(qū)域可包含的內(nèi)存對(duì)象1)可執(zhí)行文件代碼的內(nèi)存映射,代碼段(text section);2)可執(zhí)行文件已初始化全局變量的內(nèi)存映射,數(shù)據(jù)段(3)未初始化全局變量(bss 段的零頁);data section);4
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 安徽大學(xué)課題申報(bào)書
- 質(zhì)量管理qc課題申報(bào)書
- 廳級(jí)課題申報(bào)書范本
- 量感培養(yǎng)課題立項(xiàng)申報(bào)書
- 云教學(xué) 課題申報(bào)書
- 司法課題申報(bào)書
- 濟(jì)南課題申報(bào)書
- 辦學(xué)特色課題申報(bào)書
- 壓力管道維護(hù)維修合同范本
- 醫(yī)用鋼瓶銷售合同范本
- 小學(xué)生春耕教學(xué)課件
- 2025年個(gè)人投資合同電子版模板
- 車輛掛靠協(xié)議書
- 2025年湖南交通職業(yè)技術(shù)學(xué)院單招職業(yè)適應(yīng)性測(cè)試題庫1套
- 2017年公務(wù)員多省聯(lián)考《申論》真題(吉林甲級(jí)卷)及參考答案(含詳細(xì)解析)
- 《水利工程質(zhì)量檢測(cè)管理規(guī)定》知識(shí)培訓(xùn)
- 一年級(jí)下冊(cè)健康成長教案
- 2025年02月貴州省司法廳所屬事業(yè)單位公開招聘2人筆試歷年典型考題(歷年真題考點(diǎn))解題思路附帶答案詳解
- 2025年校長春季開學(xué)思政第一課講話稿1720字例文【供參考】
- 2025至2030年中國單板電磁制動(dòng)器數(shù)據(jù)監(jiān)測(cè)研究報(bào)告
- 鹽酸安非他酮合成工藝優(yōu)化-洞察分析
評(píng)論
0/150
提交評(píng)論