Linux内核分析作业第八周
進(jìn)程的切換和系統(tǒng)的一般執(zhí)行過程
一、進(jìn)程調(diào)度的時機
-
中斷處理過程(包括時鐘中斷、I/O中斷、系統(tǒng)調(diào)用和異常)中,直接調(diào)用schedule(),或者返回用戶態(tài)時根據(jù)need_resched標(biāo)記調(diào)用schedule();
-
內(nèi)核線程可以直接調(diào)用schedule()進(jìn)行進(jìn)程切換,也可以在中斷處理過程中進(jìn)行調(diào)度,也就是說內(nèi)核線程作為一類的特殊的進(jìn)程可以主動調(diào)度,也可以被動調(diào)度;
-
用戶態(tài)進(jìn)程無法實現(xiàn)主動調(diào)度,僅能通過陷入內(nèi)核態(tài)后的某個時機點進(jìn)行調(diào)度,即在中斷處理過程中進(jìn)行調(diào)度。
?
二、進(jìn)程的切換
-
為了控制進(jìn)程的執(zhí)行,內(nèi)核必須有能力掛起正在CPU上執(zhí)行的進(jìn)程,并恢復(fù)以前掛起的某個進(jìn)程的執(zhí)行,這叫做進(jìn)程切換、任務(wù)切換、上下文切換;
-
掛起正在CPU上執(zhí)行的進(jìn)程,與中斷時保存現(xiàn)場是不同的,中斷前后是在同一個進(jìn)程上下文中,只是由用戶態(tài)轉(zhuǎn)向內(nèi)核態(tài)執(zhí)行;
-
進(jìn)程上下文包含了進(jìn)程執(zhí)行需要的所有信息
-
用戶地址空間:包括程序代碼,數(shù)據(jù),用戶堆棧等
-
控制信息:進(jìn)程描述符,內(nèi)核堆棧等
-
硬件上下文(注意中斷也要保存硬件上下文只是保存的方法不同)
-
-
schedule()函數(shù)選擇一個新的進(jìn)程來運行,并調(diào)用context_switch進(jìn)行上下文的切換,這個宏調(diào)用switch_to來進(jìn)行關(guān)鍵上下文切換
- next = pick_next_task(rq, prev);//進(jìn)程調(diào)度算法都封裝這個函數(shù)內(nèi)部
- context_switch(rq, prev, next);//進(jìn)程上下文切換
-
switch_to利用了prev和next兩個參數(shù):prev指向當(dāng)前進(jìn)程,next指向被調(diào)度的進(jìn)程
?
31#define switch_to(prev, next, last) \ 32do { \ 33 /* \ 34 * Context-switching clobbers all registers, so we clobber \ 35 * them explicitly, via unused output variables. \ 36 * (EAX and EBP is not listed because EBP is saved/restored \ 37 * explicitly for wchan access and EAX is the return value of \ 38 * __switch_to()) \ 39 */ \ 40 unsigned long ebx, ecx, edx, esi, edi; \ 41 \ 42 asm volatile("pushfl\n\t" /* 保存當(dāng)前進(jìn)程的標(biāo)志位 */ \ 43 "pushl %%ebp\n\t" /* 保存當(dāng)前進(jìn)程的堆棧基址EBP */ \ 44 "movl %%esp,%[prev_sp]\n\t" /* 保存當(dāng)前棧頂ESP */ \ 45 "movl %[next_sp],%%esp\n\t" /* 把下一個進(jìn)程的棧頂放到esp寄存器中,完成了內(nèi)核堆棧的切換,從此往下壓棧都是在next進(jìn)程的內(nèi)核堆棧中。 */ \ 46 "movl $1f,%[prev_ip]\n\t" /* 保存當(dāng)前進(jìn)程的EIP */ \ 47 "pushl %[next_ip]\n\t" /* 把下一個進(jìn)程的起點EIP壓入堆棧 */ \ 48 __switch_canary \ 49 "jmp __switch_to\n" /* 因為是函數(shù)所以是jmp,通過寄存器傳遞參數(shù),寄存器是prev-a,next-d,當(dāng)函數(shù)執(zhí)行結(jié)束ret時因為沒有壓棧當(dāng)前eip,所以需要使用之前壓棧的eip,就是pop出next_ip。 */ 50 "1:\t" /* 認(rèn)為next進(jìn)程開始執(zhí)行。 */ 51 "popl %%ebp\n\t" /* restore EBP */ \ 52 "popfl\n" /* restore flags */ \ 53 /* output parameters 因為處于中斷上下文,在內(nèi)核中 prev_sp是內(nèi)核堆棧棧頂 prev_ip是當(dāng)前進(jìn)程的eip */ \ 54 /* output parameters */ \ 55 : [prev_sp] "=m" (prev->thread.sp), \ 56 [prev_ip] "=m" (prev->thread.ip), \ 57 "=a" (last), \ 58 \ 59 /* clobbered output registers: */ \ 60 "=b" (ebx), "=c" (ecx), "=d" (edx), \ 61 "=S" (esi), "=D" (edi) \ 62 \ 63 __switch_canary_oparam \ 64 \ 65 /* input parameters: */ \ 66 : [next_sp] "m" (next->thread.sp), \ 67 [next_ip] "m" (next->thread.ip), \ 68 \ 69 /* regparm parameters for __switch_to(): */ \ 70 [prev] "a" (prev), \ 71 [next] "d" (next) \ 72 \ 73 __switch_canary_iparam \ 74 \ 75 : /* reloaded segment registers */ \ 76 "memory"); \ 77} while (0)?
三、Linux系統(tǒng)的一般執(zhí)行過程
?
1、最一般的情況:正在運行的用戶態(tài)進(jìn)程X切換到運行用戶態(tài)進(jìn)程Y的過程?
正在運行的用戶態(tài)進(jìn)程X
發(fā)生中斷——save cs:eip/esp/eflags(current) to kernel stack,then load cs:eip(entry of a specific ISR) and ss:esp(point to kernel stack).
SAVE_ALL //保存現(xiàn)場
中斷處理過程中或中斷返回前調(diào)用了schedule(),其中的switch_to做了關(guān)鍵的進(jìn)程上下文切換
標(biāo)號1之后開始運行用戶態(tài)進(jìn)程Y(這里Y曾經(jīng)通過以上步驟被切換出去過因此可以從標(biāo)號1繼續(xù)執(zhí)行)
restore_all //恢復(fù)現(xiàn)場
iret - pop cs:eip/ss:esp/eflags from kernel stack
繼續(xù)運行用戶態(tài)進(jìn)程Y
?
2、幾種特殊情況
- 通過中斷處理過程中的調(diào)度時機,用戶態(tài)進(jìn)程與內(nèi)核線程之間互相切換和內(nèi)核線程之間互相切換,與最一般的情況非常類似,只是內(nèi)核線程運行過程中發(fā)生中斷沒有進(jìn)程用戶態(tài)和內(nèi)核態(tài)的轉(zhuǎn)換;
- 內(nèi)核線程主動調(diào)用schedule(),只有進(jìn)程上下文的切換,沒有發(fā)生中斷上下文的切換,與最一般的情況略簡略;
- 創(chuàng)建子進(jìn)程的系統(tǒng)調(diào)用在子進(jìn)程中的執(zhí)行起點及返回用戶態(tài),如fork;
- 加載一個新的可執(zhí)行程序后返回到用戶態(tài)的情況,如execve;
四、Linux操作系統(tǒng)架構(gòu)和系統(tǒng)執(zhí)行過程概覽
1、操作系統(tǒng)基本概念
任何計算機系統(tǒng)都包含一個基本的程序集合,稱為操作系統(tǒng)。
- 內(nèi)核(進(jìn)程管理,進(jìn)程調(diào)度,進(jìn)程間通訊機制,內(nèi)存管理,中斷異常處理,文件系統(tǒng),I/O 系統(tǒng),網(wǎng)絡(luò)部分)
- 其他程序(例如函數(shù)庫、shell程序、系統(tǒng)程序 等等)
操作系統(tǒng)的目的
- 與硬件交互,管理所有的硬件資源
- 為用戶程序(應(yīng)用程序)提供一個良好的執(zhí)行環(huán)境
2、Linux系統(tǒng)架構(gòu)
- 硬件管理
- 內(nèi)核實現(xiàn)
- 系統(tǒng)調(diào)用
- 基礎(chǔ)軟件(shell、lib)
- 用戶程序
3、最簡單也是最復(fù)雜的操作ls
?
4、站在CPU和內(nèi)存角度看Linux系統(tǒng)的執(zhí)行
?
5、從內(nèi)存的角度
五、Linux的系統(tǒng)結(jié)構(gòu)
六、用gdb對schedule進(jìn)行
1、環(huán)境搭建:
?
2、設(shè)置斷點
3、list查看斷點所在代碼段,發(fā)現(xiàn)schedule()被調(diào)用
4、c之后按n單步執(zhí)行,直到遇到__schedule函數(shù)
?
5、繼續(xù)執(zhí)行,直到發(fā)現(xiàn)context_switch函數(shù)
6、繼續(xù)單步執(zhí)行,直到發(fā)現(xiàn)context_switch函數(shù)
?
7、設(shè)置斷點后,進(jìn)入其內(nèi)部查看
轉(zhuǎn)載于:https://www.cnblogs.com/20135231hj/p/5379217.html
總結(jié)
以上是生活随笔為你收集整理的Linux内核分析作业第八周的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 灵动标签调用友情链接
- 下一篇: Android pm 命令详解