1. 程式人生 > >初學Linux中程序排程與程序切換過程

初學Linux中程序排程與程序切換過程

孫業毅 原創作品 轉載請註明出處

第八講 程序的切換和系統的一般執行過程

@2015.04

一、理論知識

Linux系統的一般執行過程

最一般的情況:正在執行的使用者態程序X切換到執行使用者態程序Y的過程

1. 正在執行的使用者態程序X

2. 發生中斷——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).

3. SAVE_ALL //儲存現場,這裡是已經進入核心中斷處裡過程

4. 中斷處理過程中或中斷返回前呼叫了schedule()

,其中的switch_to做了關鍵的程序上下文切換

5. 標號1之後開始執行使用者態程序Y(這裡Y曾經通過以上步驟被切換出去過因此可以從標號1繼續執行)

7. iret - pop cs:eip/ss:esp/eflags from kernel stack

8. 繼續執行使用者態程序Y

幾種特殊情況

  • 通過中斷處理過程中的排程時機,使用者態程序與核心執行緒之間互相切換和核心執行緒之間互相切換,與最一般的情況非常類似,只是核心執行緒執行過程中發生中斷沒有程序使用者態和核心態的轉換;
  • 核心執行緒主動呼叫schedule(),只有程序上下文的切換,沒有發生中斷上下文的切換,與最一般的情況略簡略;
  • 建立子程序的系統呼叫在子程序中的執行起點及返回使用者態,如fork
  • 載入一個新的可執行程式後返回到使用者態的情況,如execve

程序的排程時機與程序的切換

作業系統原理中介紹了大量程序排程演算法,這些演算法從實現的角度看僅僅是從執行佇列中選擇一個新程序,選擇的過程中運用了不同的策略而已。

對於理解作業系統的工作機制,反而是程序的排程時機與程序的切換機制更為關鍵。

程序排程的時機

  • 中斷處理過程(包括時鐘中斷、I/O中斷、系統呼叫和異常)中,直接呼叫schedule(),或者返回使用者態時根據need_resched標記呼叫schedule()比如sleep,就可能直接呼叫了schedule
  • 核心執行緒可以直接呼叫schedule()進行程序切換,也可以在中斷處理過程中進行排程,也就是說核心執行緒作為一類的特殊的程序
    可以主動排程,也可以被動排程;
  • 使用者態程序無法實現主動排程,僅能通過陷入核心態後的某個時機點進行排程,即在中斷處理過程中進行排程。使用者態程序只能被動排程。

程序的切換

  • 為了控制程序的執行,核心必須有能力掛起正在CPU上執行的程序,並恢復以前掛起的某個程序的執行,這叫做程序切換、任務切換、上下文切換;即程序上下文切換!
  • 掛起正在CPU上執行的程序,與中斷時儲存現場是不同的,中斷前後是在同一個程序上下文中,只是由使用者態轉向核心態執行;
  • 程序上下文包含了程序執行需要的所有資訊
    • 使用者地址空間:包括程式程式碼,資料,使用者堆疊等
    • 控制資訊:程序描述符,核心堆疊等
    • 硬體上下文(注意中斷也要儲存硬體上下文只是儲存的方法不同)
  • schedule()函式選擇一個新的程序來執行,並呼叫context_switch進行上下文的切換,這個巨集呼叫switch_to來進行關鍵上下文切換

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"      /* save    flags */    \

43           "pushl %%ebp\n\t"        /* save    EBP   */  \

44           "movl %%esp,%[prev_sp]\n\t"  /* save    ESP   */  \

45           "movl %[next_sp],%%esp\n\t"  /* restore ESP   */  \

46           "movl $1f,%[prev_ip]\n\t"    /* save    EIP   */  \

47           "pushl %[next_ip]\n\t"   /* restore EIP   */     \

48           __switch_canary                    \

49           "jmp __switch_to\n"  /* regparm call  */  \

50           "1:\t" /*下一個程序開始執行的地方!*/                        \

51           "popl %%ebp\n\t"     /* restore EBP   */     \

52           "popfl\n"         /* restore flags */   \

53                                   \

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)


二、實驗

實驗內容

1.理解Linux系統中程序排程的時機,可以在核心程式碼中搜索schedule()函式,看都是哪裡呼叫了schedule(),判斷我們課程內容中的總結是否準確;
2.使用gdb跟蹤分析一個schedule()函式 ,驗證您對Linux系統程序排程與程序切換過程的理解;推薦在實驗樓Linux虛擬機器環境下完成實驗。
3.特別關注並仔細分析switch_to中的彙編程式碼,理解程序上下文的切換機制,以及與中斷上下文切換的關係;

實驗步驟

2. 在shell中依次執行以下命令,獲取本次實驗的程式碼,並編譯執行

cd LinuxKernel

rm menu -rf

git clone https://github.com/mengning/menu.git

cd menu

mv test_exec.c test.c

make rootfs 

效果如下:



3. 關閉QEMU視窗,在shell視窗中,cd LinuxKernel回退到LinuxKernel目錄,使用下面的命令啟動核心並在CPU執行程式碼前停下以便除錯:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 

接下來,我們就可以水平分割一個新的shell窗口出來,依次使用下面的命令啟動gdb除錯

gdb

(gdb) file linux-3.18.6/vmlinux

(gdb) target remote:1234

並在系統呼叫

關閉QEMU視窗,在shell視窗中,cd LinuxKernel回退到LinuxKernel目錄,使用下面的命令啟動核心並在CPU執行程式碼前停下以便除錯:

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 

接下來,我們就可以水平分割一個新的shell窗口出來,依次使用下面的命令啟動gdb除錯

gdb

(gdb) file linux-3.18.6/vmlinux

(gdb) target remote:1234

並在核心函式schedule的入口處設定斷點,接下來輸入c繼續執行,則系統即可停在該函式處,接下來我們就可以使用命令n或者s逐步跟蹤,可以詳細瀏覽pick_next_task,switch_to等函式的執行過程,有圖為證:



相關推薦

初學Linux程序排程程序切換過程

孫業毅 原創作品 轉載請註明出處 第八講 程序的切換和系統的一般執行過程 @2015.04 一、理論知識 Linux系統的一般執行過程 最一般的情況:正在執行的使用者態程序X切換到執行使用者態程序Y的過程 1. 正在執行的使用者態程序X 2. 發生中斷——sa

Linux程序排程程序切換

Linux程序排程與程序切換 在這篇部落格裡,我們將分析在Linux中程序是如何排程和切換的。程序切換需要進行程序上下文進行排程,注意中斷也會有中斷上下文,這個跟程序上下文還有有一定區別的,中斷上下文,還是在同一個程序,不過程序上下文就是在不同程序了。下面

網易公開課《Linux核心分析》學習心得-理解程序排程時機跟蹤分析程序排程程序切換過程

首先在核心程式碼中搜索schedule,發現以下結果 在core.c檔案中是 實驗 設定斷點 跟蹤schedule的程序 可以看到 struct task_struct *tsk = current; sched_subm

第8節 理解程序排程時機跟蹤分析程序排程程序切換過程Linux核心分析】

一、實驗要求 分析並理解Linux中程序排程與程序切換過程,仔細分析程序的排程時機、switch_to及對應的堆疊狀態。需要總結並闡明自己對“Linux系統一般執行過程”的理解 二、實驗內容 理解Linux系統中程序排程的時機,可以在核心程式

分析linux程序排程程序切換

慕課18原創作品轉載請註明出處 + 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 一、Linux程序排程時機主要有: (1)主動排程: 程序的執行狀態發生變化時,例如等待某些事件而

理解程序排程時機跟蹤分析程序排程程序切換過程

“郭孟琦 + 原創作品轉載請註明出處 + 《Linux核心分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 ” 貌似是最後一週課了,竟然堅持下來了!!!! 1、在核心程式碼中搜索schedule()函式,

【讀書筆記】《Linux核心設計實現》程序管理程序排程

大學跟老師做嵌入式專案,寫過I2C的裝置驅動,但對Linux核心的瞭解也僅限於此。Android系統許多導致root的漏洞都是核心中的,研究起來很有趣,但看相關的分析文章總感覺隔著一層窗戶紙,不能完全理會。所以打算系統的學習一下Linux核心。買了兩本書《Linux核心設計與實現(第3版)》和《深入理解Lin

Linux程序排程程序執行緒的本質區別?

簡而言之,執行緒是程序的一部分,程序是程式的一部分。 異同: 1、程序是資源分配的基本單位,而執行緒是排程的基本單位; 2、程序與程序之間是獨立的,一個程序的異常終止不會影響其它程序,而執行緒與執行

【原創】(三)Linux程序排程器-程序切換

背景 Read the fucking source code! --By 魯迅 A picture is worth a thousand words. --By 高爾基 說明: Kernel版本:4.14 ARM64處理器,Contex-A53,雙核 使用工具:Source Insight 3.5,

linux編譯C語言程序

編輯器 ins spa include all 運行程序 gcc linux中 style 1.首先安裝gcc編輯器 yum install gcc* -y 2.編寫C語言程序 [[email protected]/* */ ~]# vim aa.c #i

Linux程序等待程序替換

程序的銷燬     1.釋放資源     2.記賬資訊     3.將程序狀態設定成殭屍狀態     4.轉儲存排程 程序終止的方法     正常退出         1.exit  (C庫函式)  exit函式要先執行一些清除操作,然後才將控制權交給核心          

深入Linux核心架構——鎖程序間通訊

Linux作為多工系統,當一個程序生成的資料傳輸到另一個程序時,或資料由多個程序共享時,或程序必須彼此等待時,或需要協調資源的使用時,應用程式必須彼此通訊。 一、控制機制 1、競態條件 幾個程序在訪問資源時彼此干擾的情況通常稱之為競態條件(race condition)。在對分散式應用程式設計時,這種情

Linux基礎之網路程序

1、 100.0.0.16/28 對應網段的閘道器地址、廣播地址、可分配IP地址範圍     IP地址轉化為二進位制:01100100 00000000 00000000 00010000       

第三章 程序排程死鎖

程序排程的功能 程序排程的功能由作業系統的程序程式來完成 按照某種策略和演算法從就緒態程序中為當前空閒的CPU選擇在其上執行的新程序 程序排程的功能是什麼? 按照某種策略和演算法從就緒態程序中選擇新程序執行。 需要程序排程的時機 1.程序正常或異常結束 程序阻塞 有更高優先順序程序到來,時間片用完

linux通過proc獲取程序名以及PID

背景       給定某個執行緒的執行緒號tid,獲取對應的程序名,或通過程序號獲取程序名。原始碼(通過程序名獲取程序號): void getNameByPid(pid_t pid, char *task_name) { char proc_pid_path[

Linux系統服務/守護程序 (daemon) 的詳細說明

acpid acpid(Advanced Configuration and Power Interface)是為替代傳統的APM電源管理標準而推出的新型電源管理標準。通常膝上型電腦需要啟動電源進行管理。 alsasound Alsa音效卡驅動守護程式。Alsa音效卡驅動程式本來是為了一種音

Android的Service程序間通訊(IPC)詳解

Service 什麼是Service 在後臺長期執行的沒有介面的元件。其他元件可以啟動Service讓他在後臺執行,或者繫結Service與它進行互動,甚至實現程序間通訊(IPC)。例如,可以讓服務在後臺處理網路互動,播放音樂,檔案I/O,或者與Cont

程序排程作業排程

程序排程是真正讓某個就緒狀態的程序到處理機上執行,而作業排程只是使作業具有了競爭處理機的機會。程序排程(又稱微觀排程、低階排程、短程排程): 是按照某種排程演算法從就緒狀態的程序中選擇一個程序到處理機

Linux檢視和殺死程序】-kill -9 無條件殺死

首先檢視程序: [[email protected] /]# ps -ef | grep tomcat root 1726 1 0 Apr10 ? 00:07:20 /usr/java/jdk1.6.0_22//bin/java

iOS 執行緒程序的區別

       執行緒程序的區別和聯絡     (1)一個執行緒只能屬於一個程序,而一個程序可以有多個執行緒,但至少有一個執行緒。執行緒是作業系統可識別的最小執行和排程單位。    (2)資源分