蘇州培訓(xùn)網(wǎng) > 蘇州JAVA培訓(xùn)機(jī)構(gòu) > 蘇州其然軟件開(kāi)發(fā)培訓(xùn)
首頁(yè) 培訓(xùn)網(wǎng) 最新資訊 熱門(mén)問(wèn)答

蘇州其然軟件開(kāi)發(fā)培訓(xùn)

13013833891 免費(fèi)試聽(tīng)

您當(dāng)前的位置: 蘇州IT認(rèn)證培訓(xùn) > 蘇州JAVA培訓(xùn) > 常熟市java培訓(xùn)

常熟市java培訓(xùn)_JAVA培訓(xùn)

¥詳詢

班制:周末班

蘇州其然軟件開(kāi)發(fā)
上課(咨詢)地址:蘇州市昆山市震川西路111號(hào)名仕大廈
報(bào)名咨詢 預(yù)約試聽(tīng)
課程介紹
常熟市java培訓(xùn)
教學(xué)的至高境界 分級(jí)教學(xué)

常熟市java培訓(xùn)

Java工程師就業(yè)前景

常熟市java培訓(xùn)

Java工程師就業(yè)前景

2015年,在美國(guó)、加拿大、澳大利亞、新加坡等發(fā)達(dá)國(guó)家和中等發(fā)達(dá)國(guó)家, JAVA軟件工程師年薪均在4—15萬(wàn)美金,而在國(guó)內(nèi),JAVA軟件工程師也有極好的工作機(jī)會(huì)和很高的薪水。

在未來(lái)5年內(nèi),合格軟件人才的需求將遠(yuǎn)大于供給。JAVA軟件工程師是目前 國(guó)際高端計(jì)算機(jī)領(lǐng)域就業(yè)薪資非常高的一類軟件工程師。

一般情況下的JAVA軟件工程師是分四個(gè)等級(jí),從軟件技術(shù)員到助理軟件工程 師,再到軟件工程師,**后成為高級(jí)軟件工程師。

根據(jù)IDC的統(tǒng)計(jì)數(shù)字,在所有軟件開(kāi)發(fā)類人才的需求中,對(duì)JAVA工程師的需 求達(dá)到全部需求量的60%—70%。同時(shí),JAVA軟件工程師的工資待遇相對(duì)較高。

通常來(lái)說(shuō),具有3—5年開(kāi)發(fā)經(jīng)驗(yàn)的工程師,擁有年薪15萬(wàn)元是很正常的一個(gè) 薪酬水平。80%的學(xué)生畢業(yè)后年薪都超過(guò)了8萬(wàn)元。

根據(jù)專業(yè)數(shù)據(jù)分析,由于我國(guó)經(jīng)濟(jì)發(fā)展不均衡因素,JAVA軟件工程師工資待 遇在城市之間的差異也較大,一級(jí)城市(如北京、上海等),初級(jí)軟件工程師的待遇大概在4000-6000之間,中級(jí)軟件工程師的待遇在6000—8000之間, 而高級(jí)軟件工程師的待遇基本破萬(wàn)。

JAVA 分布式大綱

常熟市java培訓(xùn)

一階段 java基礎(chǔ),我們將學(xué)習(xí)變量,基本數(shù)據(jù)類型,進(jìn)制,轉(zhuǎn)義字符,運(yùn) 算符,分支語(yǔ)句和循環(huán)語(yǔ)句等,以達(dá)到訓(xùn)練基礎(chǔ)語(yǔ)法和邏輯能力的目的。還有對(duì)數(shù)組、面向?qū)ο蠛彤惓L幚淼取?/span>

二階段 javaWeb,主要是學(xué)習(xí)Web前端開(kāi)發(fā)基礎(chǔ)和框架、Servlet和JSP在Web 后端的應(yīng)用、Web后端開(kāi)發(fā)相關(guān)專題、MVC和分層架構(gòu)以及項(xiàng)目開(kāi)發(fā)流程及CASE工具的使用等。

三階段 java框架,像框架整合開(kāi)發(fā)(SSH/SSS)、RESTful架構(gòu)和移動(dòng)端接口 設(shè)計(jì)、第三方接口和在線支付功能、網(wǎng)站安全和Spring Security應(yīng)用實(shí)戰(zhàn)、復(fù)雜用戶交互處理和Spring Web Flow的應(yīng)用、MyBatis的應(yīng)用和SSM整合等 技術(shù)點(diǎn)都是需要你掌握的。

四階段 java 云數(shù)據(jù),億級(jí)并發(fā)架構(gòu)演進(jìn)、Linux基礎(chǔ)、搭建tomcat環(huán)境以 及大數(shù)據(jù)開(kāi)發(fā)云計(jì)算等高級(jí)Java教程,是Java技術(shù)的高端知識(shí)。其中穿插項(xiàng)目實(shí)戰(zhàn)演練,企業(yè)真實(shí)項(xiàng)目供學(xué)員應(yīng)用學(xué)習(xí),進(jìn)行知識(shí)體系的“二次學(xué)習(xí)” 。

進(jìn)程切換(context_switch)代碼分析:基本邏輯


>

http://www.wowotech.net/PRocess_management/context-switch-arch.html

一、前言

本文主要是以context_switch為起點(diǎn),分析了整個(gè)進(jìn)程切換過(guò)程中的基本操作和基本的代碼框架,很多細(xì)節(jié),例如tlb的操作,cache的操作,鎖的操作等等會(huì)在其他專門(mén)的文檔中描述。進(jìn)程切換包括體系結(jié)構(gòu)相關(guān)的代碼和系統(tǒng)結(jié)構(gòu)無(wú)關(guān)的代碼。第二、三、四分別描述了context_switch的代碼脈絡(luò),后面的章節(jié)是以ARM64為例子,講述了具體進(jìn)程地址空間的切換過(guò)程和硬件上下文的切換過(guò)程。

 

二、context_switch代碼分析

在kernel/sched/core.c中有一個(gè)context_switch函數(shù),該函數(shù)用來(lái)完成具體的進(jìn)程切換,代碼如下(本文主要描述進(jìn)程切換的基本邏輯,因此部分代碼會(huì)有刪節(jié)):

static inline struct rq * context_switch(struct rq *rq, struct task_struct *prev,             struct task_struct *next)------------------(1)  {      struct mm_struct *mm, *oldmm;

    mm = next->mm;      oldmm = prev->active_mm;-------------------(2)

    if (!mm) {---------------------------(3)          next->active_mm = oldmm;          atomic_inc(&oldmm->mm_count);          enter_lazy_tlb(oldmm, next);-----------------(4)      } else          switch_mm(oldmm, mm, next); ---------------(5)

    if (!prev->mm) {------------------------(6)          prev->active_mm = NULL;          rq->prev_mm = oldmm;      }

    switch_to(prev, next, prev);------------------(7)      barrier();

    return finish_task_switch(prev);  }

(1)一旦調(diào)度器算法確定了pre task和next task,那么就可以調(diào)用context_switch函數(shù)實(shí)際執(zhí)行進(jìn)行切換的工作了,這里我們先看看參數(shù)傳遞情況:

  rq:在多核系統(tǒng)中,進(jìn)程切換總是發(fā)生在各個(gè)cpu core上,參數(shù)rq指向本次切換發(fā)生的那個(gè)cpu對(duì)應(yīng)的run queue    prev:將要被剝奪執(zhí)行權(quán)利的那個(gè)進(jìn)程    next:被選擇在該cpu上執(zhí)行的那個(gè)進(jìn)程

(2)next是馬上就要被切入的進(jìn)程(后面簡(jiǎn)稱B進(jìn)程),prev是馬上就要被剝奪執(zhí)行權(quán)利的進(jìn)程(后面簡(jiǎn)稱A進(jìn)程)。mm變量指向B進(jìn)程的地址空間描述符,oldmm變量指向A進(jìn)程的當(dāng)前正在使用的地址空間描述符(active_mm)。對(duì)于normal進(jìn)程,其任務(wù)描述符(task_struct)的mm和active_mm相同,都是指向其進(jìn)程地址空間。對(duì)于內(nèi)核線程而言,其task_struct的mm成員為NULL(內(nèi)核線程沒(méi)有進(jìn)程地址空間),但是,內(nèi)核線程被調(diào)度執(zhí)行的時(shí)候,總是需要一個(gè)進(jìn)程地址空間,而active_mm就是指向它借用的那個(gè)進(jìn)程地址空間。

(3)mm為空的話,說(shuō)明B進(jìn)程是內(nèi)核線程,這時(shí)候,只能借用A進(jìn)程當(dāng)前正在使用的那個(gè)地址空間(prev->active_mm)。注意:這里不能借用A進(jìn)程的地址空間(prev->mm),因?yàn)锳進(jìn)程也可能是一個(gè)內(nèi)核線程,不擁有自己的地址空間描述符。

(4)如果要切入的B進(jìn)程是內(nèi)核線程,那么調(diào)用體系結(jié)構(gòu)相關(guān)的代碼enter_lazy_tlb,標(biāo)識(shí)該cpu進(jìn)入lazy tlb mode。那么什么是lazy tlb mode呢?如果要切入的進(jìn)程實(shí)際上是內(nèi)核線程,那么我們也暫時(shí)不需要flush TLB,因?yàn)閮?nèi)核線程不會(huì)訪問(wèn)usersapce,所以那些無(wú)效的TLB entry也不會(huì)影響內(nèi)核線程的執(zhí)行。在這種情況下,為了性能,我們會(huì)進(jìn)入lazy tlb mode。進(jìn)程切換中和TLB相關(guān)的內(nèi)容我們會(huì)單獨(dú)在一篇文章中描述,這里就不再贅述了。

(5)如果要切入的B進(jìn)程是內(nèi)核線程,那么由于是借用當(dāng)前正在使用的地址空間,因此沒(méi)有必要調(diào)用switch_mm進(jìn)行地址空間切換,只有要切入的B進(jìn)程是一個(gè)普通進(jìn)程的情況下(有自己的地址空間)才會(huì)調(diào)用switch_mm,真正執(zhí)行地址空間切換。

如果切入的是普通進(jìn)程,那么這時(shí)候進(jìn)程的地址空間已經(jīng)切換了,也就是說(shuō)在A--->B進(jìn)程的過(guò)程中,進(jìn)程本身尚未切換,而進(jìn)程的地址空間已經(jīng)切換到了B進(jìn)程了。這樣會(huì)不會(huì)造成問(wèn)題呢?還好,呵呵,這時(shí)候代碼執(zhí)行在kernel space,A和B進(jìn)程的kernel space都是一樣一樣的啊,即便是切了進(jìn)程地址空間,不過(guò)內(nèi)核空間實(shí)際上保持不變的。

(6)如果切出的A進(jìn)程是內(nèi)核線程,那么其借用的那個(gè)地址空間(active_mm)已經(jīng)不需要繼續(xù)使用了(內(nèi)核線程A被掛起了,根本不需要地址空間了)。除此之外,我們這里還設(shè)定了run queue上一次使用的mm struct(rq->prev_mm)為oldmm。為何要這么做?先等一等,下面我們會(huì)統(tǒng)一描述。

(7)一次進(jìn)程切換,表面上看起來(lái)涉及兩個(gè)進(jìn)程,實(shí)際上涉及到了三個(gè)進(jìn)程。switch_to是一個(gè)有魔力的符號(hào),和一般的調(diào)用函數(shù)不同,當(dāng)A進(jìn)程在CPUa調(diào)用它切換到B進(jìn)程的時(shí)候,switch_to一去不回,直到在某個(gè)cpu上(我們稱之CPUx)完成從X進(jìn)程(就是last進(jìn)程)到A進(jìn)程切換的時(shí)候,switch_to返回到A進(jìn)程的現(xiàn)場(chǎng)。這一點(diǎn)我們會(huì)在下一節(jié)詳細(xì)描述。switch_to完成了具體prev到next進(jìn)程的切換,當(dāng)switch_to返回的時(shí)候,說(shuō)明A進(jìn)程再次被調(diào)度執(zhí)行了。

 

三、switch_to為什么需要三個(gè)參數(shù)呢?

switch_to定義如下:

#define switch_to(prev, next, last)                    \      do {                                \          ((last) = __switch_to((prev), (next)));            \      } while (0)

一個(gè)switch_to將代碼分成兩段:

AAA

switch_to(prev, next, prev);

BBB

一次進(jìn)程切換,涉及到了三個(gè)進(jìn)程,prev和next是大家都熟悉的參數(shù)了,對(duì)于進(jìn)程A(下圖中的右半圖片),如果它想要切換到B進(jìn)程,那么:      prev=A      next=B 

這時(shí)候,在A進(jìn)程中調(diào)用 switch_to 完成A到B進(jìn)程的切換。但是,當(dāng)經(jīng)歷萬(wàn)水千山,A進(jìn)程又被重新調(diào)度的時(shí)候,我們又來(lái)到了switch_to返回的這一點(diǎn)(下圖中的左半圖片),這時(shí)候,我們是從哪一個(gè)進(jìn)程切換到A呢?誰(shuí)知道呢(在A進(jìn)程調(diào)用switch_to 的時(shí)候是不知道的)?在A進(jìn)程調(diào)用switch_to之后,cpu就執(zhí)行B進(jìn)程了,后續(xù)B進(jìn)程切到哪個(gè)進(jìn)程呢?隨后又經(jīng)歷了怎樣的進(jìn)程切換過(guò)程呢?當(dāng)然,這一切對(duì)于A進(jìn)程來(lái)說(shuō)它并不關(guān)心,它唯一關(guān)心的是當(dāng)切換回A進(jìn)程的時(shí)候,該cpu上(也不一定是A調(diào)用switch_to切換到B進(jìn)程的那個(gè)CPU)執(zhí)行的上一個(gè)task是誰(shuí)?這就是第三個(gè)參數(shù)的含義(實(shí)際上這個(gè)參數(shù)的名字就是last,也基本說(shuō)明了其含義)。也就是說(shuō),在AAA點(diǎn)上,prev是A進(jìn)程,對(duì)應(yīng)的run queue是CPUa的run queue,而在BBB點(diǎn)上,A進(jìn)程恢復(fù)執(zhí)行,last是X進(jìn)程,對(duì)應(yīng)的run queue是CPUx的run queue。

 

四、在內(nèi)核線程切換過(guò)程中,內(nèi)存描述符的處理

我們上面已經(jīng)說(shuō)過(guò):如果切入內(nèi)核線程,那么其實(shí)進(jìn)程地址空間實(shí)際上并沒(méi)有切換,該內(nèi)核線程只是借用了切出進(jìn)程使用的那個(gè)地址空間(active_mm)。對(duì)于內(nèi)核中的實(shí)體,我們都會(huì)使用引用計(jì)數(shù)來(lái)根據(jù)一個(gè)數(shù)據(jù)對(duì)象,從而確保在沒(méi)有任何引用的情況下釋放該數(shù)據(jù)對(duì)象實(shí)體,對(duì)于內(nèi)存描述符亦然。因此,在context_switch中有代碼如下:

if (!mm) {      next->active_mm = oldmm;      atomic_inc(&oldmm->mm_count);-----增加引用計(jì)數(shù)      enter_lazy_tlb(oldmm, next);  }

既然是借用別人的內(nèi)存描述符(地址空間),那么調(diào)用atomic_inc是合理的,反正馬上就切入B進(jìn)程了,在A進(jìn)程中提前增加引用計(jì)數(shù)也OK的。話說(shuō)有借有還,那么在內(nèi)核線程被切出的時(shí)候,就是歸還內(nèi)存描述符的時(shí)候了。

這里還有一個(gè)悖論,對(duì)于內(nèi)核線程而言,在運(yùn)行的時(shí)候,它會(huì)借用其他進(jìn)程的地址空間,因此,在整個(gè)內(nèi)核線程運(yùn)行過(guò)程中,需要使用該地址空間(內(nèi)存描述符),因此對(duì)內(nèi)存描述符的增加和減少引用計(jì)數(shù)的操作只能在在內(nèi)核線程之外完成。假如一次切換是這樣的:…A--->B(內(nèi)核線程)--->C…,增加引用計(jì)數(shù)比較簡(jiǎn)單,上面已經(jīng)說(shuō)了,在A進(jìn)程調(diào)用context_switch的時(shí)候完成。現(xiàn)在問(wèn)題來(lái)了,如何在C中完成減少引用計(jì)數(shù)的操作呢?我們還是從代碼中尋找答案,如下(context_switch函數(shù)中,去掉了不相關(guān)的代碼):

if (!prev->mm) {      prev->active_mm = NULL;      rq->prev_mm = oldmm;---在rq->prev_mm上保存了上一次使用的mm struct  }

借助其他進(jìn)程內(nèi)存描述符的東風(fēng),內(nèi)核線程B歡快的運(yùn)行,然而,快樂(lè)總是短暫的,也許是B自愿的,也許是強(qiáng)迫的,調(diào)度器**終會(huì)剝奪B的執(zhí)行,切入C進(jìn)程。也就是說(shuō),B內(nèi)核線程調(diào)用switch_to(執(zhí)行了AAA段代碼),自己掛起,C粉墨登場(chǎng),執(zhí)行BBB段的代碼。具體的代碼在finish_task_switch,如下:

static struct rq *finish_task_switch(struct task_struct *prev)  {      struct rq *rq = this_rq();      struct mm_struct *mm = rq->prev_mm;――――――――――――――――(1)

    rq->prev_mm = NULL;

    if (mm)          mmdrop(mm);――――――――――――――――――――――――(2)  }

(1)我們假設(shè)B是內(nèi)核線程,在進(jìn)程A調(diào)用context_switch切換到B線程的時(shí)候,借用的地址空間被保存在CPU對(duì)應(yīng)的run queue中。在B切換到C之后,**rq->prev_mm就可以得到借用的內(nèi)存描述符。

(2)已經(jīng)完成B到C的切換后,借用的地址空間可以返還了。因此在C進(jìn)程中調(diào)用mmdrop來(lái)完成這一動(dòng)作。很神奇,在A進(jìn)程中為內(nèi)核線程B借用地址空間,但卻在C進(jìn)程中釋放它。

 

五、ARM64的進(jìn)程地址空間切換

對(duì)于ARM64這個(gè)cpu arch,每一個(gè)cpu core都有兩個(gè)寄存器來(lái)指示當(dāng)前運(yùn)行在該CPU core上的進(jìn)程(線程)實(shí)體的地址空間。這兩個(gè)寄存器分別是ttbr0_el1(用戶地址空間)和ttbr1_el1(內(nèi)核地址空間)。由于所有的進(jìn)程共享內(nèi)核地址空間,因此所謂地址空間切換也就是切換ttbr0_el1而已。地址空間聽(tīng)起來(lái)很抽象,實(shí)際上就是內(nèi)存中的若干Translation table而已,每一個(gè)進(jìn)程都有自己獨(dú)立的一組用于翻譯用戶空間虛擬地址的Translation table,這些信息保存在內(nèi)存描述符中,具體位于struct mm_struct中的pgd成員中。以pgd為起點(diǎn),可以遍歷該內(nèi)存描述符的所有用戶地址空間的Translation table。具體代碼如下:

static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,        struct task_struct *tsk)----------------(1)  {      unsigned int cpu = smp_processor_id();

    if (prev == next)--------------------(2)          return;

    if (next == &init_mm) {-----------------(3)          cpu_set_reserved_ttbr0();          return;      }

    check_and_switch_context(next, cpu);  }

(1)prev是要切出的地址空間,next是要切入的地址空間,tsk是將要切入的進(jìn)程。

(2)要切出的地址空間和要切入的地址空間是一個(gè)地址空間的話,那么切換地址空間也就沒(méi)有什么意義了。

(3)在ARM64中,地址空間的切換主要是切換ttbr0_el1,對(duì)于swapper進(jìn)程的地址空間,其用戶空間沒(méi)有任何的mapping,而如果要切入的地址空間就是swapper進(jìn)程的地址空間的時(shí)候,將(設(shè)定ttbr0_el1指向empty_zero_page)。

(4)check_and_switch_context中有很多TLB、ASID相關(guān)的操作,我們將會(huì)在另外的文檔中給出細(xì)致描述,這里就簡(jiǎn)單略過(guò),實(shí)際上,**終該函數(shù)會(huì)調(diào)用arch/arm64/mm/proc.S文件中的cpu_do_switch_mm將要切入進(jìn)程的L0 Translation table物理地址(保存在內(nèi)存描述符的pgd成員)寫(xiě)入ttbr0_el1。

 

六、ARM64的的進(jìn)程切換

由于存在MMU,內(nèi)存中可以有多個(gè)task,并且由調(diào)度器依次調(diào)度到cpu core上實(shí)際執(zhí)行。系統(tǒng)有多少個(gè)cpu core就可以有多少個(gè)進(jìn)程(線程)同時(shí)執(zhí)行。即便是對(duì)于一個(gè)特定的cpu core,調(diào)度器可以可以不斷的將控制權(quán)從一個(gè)task切換到另外一個(gè)task上。實(shí)際的context switch的動(dòng)作也不復(fù)雜:就是將當(dāng)前的上下文保存在內(nèi)存中,然后從內(nèi)存中恢復(fù)另外一個(gè)task的上下文。對(duì)于ARM64而言,context包括:

(1)通用寄存器

(2)浮點(diǎn)寄存器

(3)地址空間寄存器(ttbr0_el1和ttbr1_el1),上一節(jié)已經(jīng)描述

(4)其他寄存器(ASID、thread process ID register等)

__switch_to代碼(位于arch/arm64/kernel/process.c)如下:

struct task_struct *__switch_to(struct task_struct *prev,                  struct task_struct *next)  {      struct task_struct *last;

    fpsimd_thread_switch(next);--------------(1)      tls_thread_switch(next);----------------(2)      hw_breakpoint_thread_switch(next);--和硬件跟蹤相關(guān)      contextidr_thread_switch(next); --和硬件跟蹤相關(guān)

    dsb(ish);       last = cpu_switch_to(prev, next); ------------(3)

    return last;  }

(1)fp是float-point的意思,和浮點(diǎn)運(yùn)算相關(guān)。simd是Single Instruction Multiple Data的意思,和多媒體以及信號(hào)處理相關(guān)。fpsimd_thread_switch其實(shí)就是把當(dāng)前FPSIMD的狀態(tài)保存到了內(nèi)存中(task.thread.fpsimd_state),從要切入的next進(jìn)程描述符中獲取FPSIMD狀態(tài),并加載到CPU上。

(2)概念同上,不過(guò)是處理tls(thread local storage)的切換。這里硬件寄存器涉及tpidr_el0和tpidrro_el0,涉及的內(nèi)存是task.thread.tp_value。具體的應(yīng)用場(chǎng)景是和線程庫(kù)相關(guān),具體大家可以自行學(xué)習(xí)了。

(3)具體的切換發(fā)生在arch/arm64/kernel/entry.S文件中的cpu_switch_to,代碼如下:

ENTRY(cpu_switch_to) -------------------(1)      mov    x10, #THREAD_CPU_CONTEXT ----------(2)      add    x8, x0, x10 --------------------(3)      mov    x9, sp      stp    x19, x20, [x8], #16----------------(4)      stp    x21, x22, [x8], #16      stp    x23, x24, [x8], #16      stp    x25, x26, [x8], #16      stp    x27, x28, [x8], #16      stp    x29, x9, [x8], #16      str    lr, [x8] ---------A      add    x8, x1, x10 -------------------(5)      ldp    x19, x20, [x8], #16----------------(6)      ldp    x21, x22, [x8], #16      ldp    x23, x24, [x8], #16      ldp    x25, x26, [x8], #16      ldp    x27, x28, [x8], #16      ldp    x29, x9, [x8], #16      ldr    lr, [x8] -------B      mov    sp, x9 -------C      ret -------------------------(7)  ENDPROC(cpu_switch_to)

(1)進(jìn)入cpu_switch_to函數(shù)之前,x0,x1用做參數(shù)傳遞,x0是prev task,就是那個(gè)要掛起的task,x1是next task,就是馬上要切入的task。cpu_switch_to和其他的普通函數(shù)沒(méi)有什么不同,盡管會(huì)走遍萬(wàn)水千山,但是**終還是會(huì)返回調(diào)用者函數(shù)__switch_to。

在進(jìn)入細(xì)節(jié)之前,先想一想這個(gè)問(wèn)題:cpu_switch_to要如何保存現(xiàn)場(chǎng)?要保存那些通用寄存器呢?其實(shí)上一小段描述已經(jīng)做了鋪陳:盡管有點(diǎn)怪異,本質(zhì)上cpu_switch_to仍然是一個(gè)普通函數(shù),需要符合ARM64標(biāo)準(zhǔn)過(guò)程調(diào)用文檔。在該文檔中規(guī)定,x19~x28是屬于callee-saved registers,也就是說(shuō),在__switch_to函數(shù)調(diào)用cpu_switch_to函數(shù)這個(gè)過(guò)程中,cpu_switch_to函數(shù)要保證x19~x28這些寄存器值是和調(diào)用cpu_switch_to函數(shù)之前一模一樣的。除此之外,pc、sp、fp當(dāng)然也是必須是屬于現(xiàn)場(chǎng)的一部分的。

(2)得到THREAD_CPU_CONTEXT的偏移,保存在x10中

(3)x0是pre task的進(jìn)程描述符,加上偏移之后就獲取了訪問(wèn)cpu context內(nèi)存的指針(x8寄存器)。所有context的切換的原理都是一樣的,就是把當(dāng)前cpu寄存器保存在內(nèi)存中,這里的內(nèi)存是在進(jìn)程描述符中的 thread.cpu_context中。

(4)一旦定位到保存cpu context(各種通用寄存器)的內(nèi)存,那么使用stp保存硬件現(xiàn)場(chǎng)。這里x29就是fp(frame pointer),x9保存了stack pointer,lr是返回的PC值。到A代碼處,完成了pre task cpu context的保存動(dòng)作。

(5)和步驟(3)類似,只不過(guò)是針對(duì)next task而言的。這時(shí)候x8指向了next task的cpu context。

(6)和步驟(4)類似,不同的是這里的操作是恢復(fù)next task的cpu context。執(zhí)行到代碼B處,所有的寄存器都已經(jīng)恢復(fù),除了PC和SP,其中PC保存在了lr(x30)中,而sp保存在了x9中。在代碼C出恢復(fù)了sp值,這時(shí)候萬(wàn)事俱備,只等PC操作了。

(7)ret指令其實(shí)就是把x30(lr)寄存器的值加載到PC,至此現(xiàn)場(chǎng)完全恢復(fù)到調(diào)用cpu_switch_to那一點(diǎn)上了。

 

參考文獻(xiàn):

1、ARM標(biāo)準(zhǔn)過(guò)程調(diào)用文檔(IHI0056C_beta_aaelf64.pdf)

2、linux 4.4.6內(nèi)核源代碼


相關(guān)推薦:


蘇州JAVA培訓(xùn)   蘇州JAVA培訓(xùn)班   蘇州JAVA培訓(xùn)機(jī)構(gòu)

體驗(yàn)課預(yù)約試聽(tīng)

倒計(jì)時(shí)

12:00:00

課程熱線:

13013833891
在線咨詢

客服在線時(shí)間:早上9點(diǎn)~下午6點(diǎn),其他時(shí)間請(qǐng)?jiān)诰€預(yù)約報(bào)名或留言,謝謝!

蘇州JAVA

免費(fèi)體驗(yàn)課開(kāi)班倒計(jì)時(shí)

11: 41: 09

稍后會(huì)有專業(yè)老師給您回電,請(qǐng)保持電話暢通

咨詢電話:13013833891
推薦機(jī)構(gòu) 全國(guó)分站 更多課程

本周僅剩 個(gè)試聽(tīng)名額

請(qǐng)鍵入信息,稍后系統(tǒng)將會(huì)把領(lǐng)獎(jiǎng)短信發(fā)至您的手機(jī)

申請(qǐng)?jiān)嚶?tīng)名額

已有10254人申請(qǐng)免費(fèi)試聽(tīng)

01電話咨詢 | 13013833891

QQ:1413838287
加盟合作:0755-83654572