日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux kernel进程切换(寄存器保存与恢复)

發布時間:2025/3/21 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux kernel进程切换(寄存器保存与恢复) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在threadA執行時,被調度了執行了threadB, 那么在threadB執行完之后是如何恢復threadA進程能夠繼續執行的呢?

我們從代碼中去尋找答案, 系統調度是schedule()函數,那么我們就從schedule()函數看起
schedule() --> __schedule(true) --> context_switch(rq, prev,next) --> switch_to(prev, next, prev) --> __switch_to((prev), (next))

/** Thread switching.*/ struct task_struct *__switch_to(struct task_struct *prev,struct task_struct *next) {struct task_struct *last;fpsimd_thread_switch(next);tls_thread_switch(next);hw_breakpoint_thread_switch(next);contextidr_thread_switch(next); #ifdef CONFIG_THREAD_INFO_IN_TASKentry_task_switch(next); #endifuao_thread_switch(next);/** Complete any pending TLB or cache maintenance on this CPU in case* the thread migrates to a different CPU.*/dsb(ish);/* the actual thread switch */last = cpu_switch_to(prev, next);return last; }

1、通用寄存器的保存
schedule() --> __schedule(true) --> context_switch(rq, prev,next) --> switch_to(prev, next, prev) --> __switch_to((prev), (next)) --> cpu_switch_to(prev, next)

/** Register switch for AArch64. The callee-saved registers need to be saved* and restored. On entry:* x0 = previous task_struct (must be preserved across the switch)* x1 = next task_struct* Previous and next are guaranteed not to be the same.**/ ENTRY(cpu_switch_to)mov x10, #THREAD_CPU_CONTEXTadd x8, x0, x10 // previous task_struct + THREAD_CPU_CONTEXT,X8為前一個進程的struct cpu_context結構體指針mov x9, spstp x19, x20, [x8], #16 // store callee-saved registers &&&& 壓棧 &&&&stp x21, x22, [x8], #16stp x23, x24, [x8], #16stp x25, x26, [x8], #16stp x27, x28, [x8], #16stp x29, x9, [x8], #16str lr, [x8] // lr壓棧add x8, x1, x10 // next task_struct + THREAD_CPU_CONTEXT,X8為后一個進程的struct cpu_context結構體指針ldp x19, x20, [x8], #16 // restore callee-saved registers &&&& 出棧 &&&&ldp x21, x22, [x8], #16ldp x23, x24, [x8], #16ldp x25, x26, [x8], #16ldp x27, x28, [x8], #16ldp x29, x9, [x8], #16ldr lr, [x8] lr出棧mov sp, x9 #ifdef CONFIG_THREAD_INFO_IN_TASKmsr sp_el0, x1 #elseand x9, x9, #~(THREAD_SIZE - 1)msr sp_el0, x9 #endifret ENDPROC(cpu_switch_to)

根據ARM標準文檔描述<IHI0056C_beta_aaelf64.pdf>, x19~x28是屬于
callee-saved registers,需要保存,此外sp,lr,pc也需要保存

THREAD_CPU_CONTEXT為thread.cpu_context在struct task_struct結構體中的偏移

DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context)); struct task_struct {......struct thread_struct thread;}; struct thread_struct {struct cpu_context cpu_context; /* cpu context */unsigned long tp_value; /* TLS register */ #ifdef CONFIG_COMPATunsigned long tp2_value; #endifstruct fpsimd_state fpsimd_state;unsigned long fault_address; /* fault info */unsigned long fault_code; /* ESR_EL1 value */struct debug_info debug; /* debugging */ } struct cpu_context {unsigned long x19;unsigned long x20;unsigned long x21;unsigned long x22;unsigned long x23;unsigned long x24;unsigned long x25;unsigned long x26;unsigned long x27;unsigned long x28;unsigned long fp;unsigned long sp;unsigned long pc; };

問與答:
關于前面的一段匯編,上面stp的一段是壓棧,將前一個進程的寄存器保存起來。
后面ldp的一段是出棧,將后一個進程的寄存器恢復出來。
關于棧,不都是先進后出嗎? 為何這里是先進先出、后進后出?

在arm32上,是PUSH,POP等指令,是先進后出
到了arm64上,沒有了PUSH POP指令,取而代之的是STP LDP,這個指令其實就是讀寄存器,沒有"先進/后進/先出/后出"等概念了,你想怎么進就怎么進,想怎么出就怎么出

總結

以上是生活随笔為你收集整理的linux kernel进程切换(寄存器保存与恢复)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。