Linux中的棧

來源:互聯網
上載者:User

copy from http://blog.csdn.net/chenglian_999/article/details/4785720

以前我在看關於Linux原理的內容的時候,總遇到什麼核心棧、使用者棧。今天單獨的看了一下Linux中棧的使用,在這裡作一下總結。

一、linux中的堆棧

      Linux0.11核中總共涉及到了四種棧:系統引導時候的臨時棧;核心初始化使用的棧;核心態棧;使用者態棧。

1)  系統引導時候的臨時棧

在boosetct中,當它把自身移動到0x90000處時候,就會設定臨時棧,以0x90000為段地址,0xff00為位移地址。

Setup中也沿用了這個棧,作為系統引導的臨時棧。

2) 核心初始化使用的棧

在進入保護模式執行head的時候,棧的段地址設定在核心的資料區段地址處(此時ss中儲存的不再是具體的基地址了,而是堆棧段選擇符,當然也是資料區段的選擇符),棧頂指標指向user_stack數組頂端,保留一頁記憶體作為堆棧。

在進入main進行系統初始化的時候,沿用head中設定的棧,但在move_to_user_mode()之後,代碼的執行切換到了任務0,在任務0中用建立了任務1,任務1使用的是自己棧(在任務1的task_struct中的tss中指出)。而任務0仍然使用之前使用的棧作為它的使用者棧。

3)  使用者態棧

當使用者進程在啟動並執行時候,會涉及到程序呼叫等棧操作,此時它用的是使用者棧,使用者棧的基地址是任務的資料區段基地址,棧頂指標在靠近線性地址空間的頂端處(只是靠近頂端,最頂端存放的是命令列參數和環境變數)。它使用的實際物理頁是在“寫時複製”時分配的得到的。

4)  核心態棧

當使用者進程執行核心代碼的時候,例如系統調用,就會使用核心態棧,每個任務都有自己的核心態棧,它的物理位置處在此任務的task_struct所在頁中,具體的基地址和棧頂指標由tss中的ss0和esp0指定。

二、使用者態棧和核心態棧的切換

執行任務切換的時候,毫無疑問會發生棧的切換,它使用的堆棧會發生變化,它的切換是兩個任務的使用者棧間的切換,是通過TSS完成的;而當CPU的特權級發生變化的時候,它使用的堆棧也會發生變化,而這時的切換是同一任務的使用者棧和核心棧的切換。下面我就說一下使用者態棧和核心態棧的切換的大致過程。

在0.11核中所有的中斷都屬於核心代碼,所以如果一個中斷產生時,任務正運行使用者代碼,也就是運行在使用者態,那麼就會引起任務從使用者態(特權級3)向核心態(特權級0)的轉變,此時就會發生從使用者態棧到核心態棧的切換。CPU先從task_struct中的TSS中獲得核心態棧的地址,然後把使用者態棧的段地址、棧頂指標壓入核心態棧,隨後再把eflags、es、ip也壓入堆棧。接著執行中斷處理常式,此時使用的是核心態棧。執行完中斷處理常式返回的時候,iret會返回到使用者模式,恢複使用者棧和eflags。這樣就又使用使用者棧。

注釋:如果處在核心態,中斷的時候,cpu並不進行ss、esp的棧操作。

三、任務0中的棧切換

    在核心初時話過程中,會將代碼的執行交給任務0(move_to_user_mode),任務0的核心棧在它自己的任務資料結構所在頁面的末端,而任務0的使用者棧是之前CPU進入保護模式時候用的棧,即usr_stack[],把它設定為任務0的使用者棧是利用手工設定的:當執行iret的時候,如果發生了特權級的變化,iret還要把棧中的棧基址和棧頂指標也同時恢複,那麼在move_to_user_mode()中,LINUX手工地把任務0的使用者棧的基址和棧頂指標壓入堆棧,同時把任務0的eflag、cs、ip壓入堆棧,注意此時壓入的SS,CS雖然也指向模式轉換之前的段,但是它門包括了特權級的資訊,所以當cs出棧的時候,發現它的特權級(3)與現在的(0)不同,而且低於現在的,所以就會還會再把新棧的SS和esp出來。這樣代碼的執行就交給了處在使用者模式下的任務0,在任務0中再建立任務1.......

copy from http://blog.csdn.net/chenglian_999/article/details/4785720

以前我在看關於Linux原理的內容的時候,總遇到什麼核心棧、使用者棧。今天單獨的看了一下Linux中棧的使用,在這裡作一下總結。

一、linux中的堆棧

      Linux0.11核中總共涉及到了四種棧:系統引導時候的臨時棧;核心初始化使用的棧;核心態棧;使用者態棧。

1)  系統引導時候的臨時棧

在boosetct中,當它把自身移動到0x90000處時候,就會設定臨時棧,以0x90000為段地址,0xff00為位移地址。

Setup中也沿用了這個棧,作為系統引導的臨時棧。

2) 核心初始化使用的棧

在進入保護模式執行head的時候,棧的段地址設定在核心的資料區段地址處(此時ss中儲存的不再是具體的基地址了,而是堆棧段選擇符,當然也是資料區段的選擇符),棧頂指標指向user_stack數組頂端,保留一頁記憶體作為堆棧。

在進入main進行系統初始化的時候,沿用head中設定的棧,但在move_to_user_mode()之後,代碼的執行切換到了任務0,在任務0中用建立了任務1,任務1使用的是自己棧(在任務1的task_struct中的tss中指出)。而任務0仍然使用之前使用的棧作為它的使用者棧。

3)  使用者態棧

當使用者進程在啟動並執行時候,會涉及到程序呼叫等棧操作,此時它用的是使用者棧,使用者棧的基地址是任務的資料區段基地址,棧頂指標在靠近線性地址空間的頂端處(只是靠近頂端,最頂端存放的是命令列參數和環境變數)。它使用的實際物理頁是在“寫時複製”時分配的得到的。

4)  核心態棧

當使用者進程執行核心代碼的時候,例如系統調用,就會使用核心態棧,每個任務都有自己的核心態棧,它的物理位置處在此任務的task_struct所在頁中,具體的基地址和棧頂指標由tss中的ss0和esp0指定。

二、使用者態棧和核心態棧的切換

執行任務切換的時候,毫無疑問會發生棧的切換,它使用的堆棧會發生變化,它的切換是兩個任務的使用者棧間的切換,是通過TSS完成的;而當CPU的特權級發生變化的時候,它使用的堆棧也會發生變化,而這時的切換是同一任務的使用者棧和核心棧的切換。下面我就說一下使用者態棧和核心態棧的切換的大致過程。

在0.11核中所有的中斷都屬於核心代碼,所以如果一個中斷產生時,任務正運行使用者代碼,也就是運行在使用者態,那麼就會引起任務從使用者態(特權級3)向核心態(特權級0)的轉變,此時就會發生從使用者態棧到核心態棧的切換。CPU先從task_struct中的TSS中獲得核心態棧的地址,然後把使用者態棧的段地址、棧頂指標壓入核心態棧,隨後再把eflags、es、ip也壓入堆棧。接著執行中斷處理常式,此時使用的是核心態棧。執行完中斷處理常式返回的時候,iret會返回到使用者模式,恢複使用者棧和eflags。這樣就又使用使用者棧。

注釋:如果處在核心態,中斷的時候,cpu並不進行ss、esp的棧操作。

三、任務0中的棧切換

    在核心初時話過程中,會將代碼的執行交給任務0(move_to_user_mode),任務0的核心棧在它自己的任務資料結構所在頁面的末端,而任務0的使用者棧是之前CPU進入保護模式時候用的棧,即usr_stack[],把它設定為任務0的使用者棧是利用手工設定的:當執行iret的時候,如果發生了特權級的變化,iret還要把棧中的棧基址和棧頂指標也同時恢複,那麼在move_to_user_mode()中,LINUX手工地把任務0的使用者棧的基址和棧頂指標壓入堆棧,同時把任務0的eflag、cs、ip壓入堆棧,注意此時壓入的SS,CS雖然也指向模式轉換之前的段,但是它門包括了特權級的資訊,所以當cs出棧的時候,發現它的特權級(3)與現在的(0)不同,而且低於現在的,所以就會還會再把新棧的SS和esp出來。這樣代碼的執行就交給了處在使用者模式下的任務0,在任務0中再建立任務1.......

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.