orig_ax ; enter_from_user_mode() ; local_irq_enable() ; if ( READ_ONCE ( ti- >flags) /* * NB: Native and x32 syscalls are dispatched from the same * table. The only functional difference is the x32 bit in * regs- >orig_ax, which changes the behavior of some syscalls. */ if ( likely (( nr __SYSCALL_MASK]( regs- >di, regs- >si, regs- >dx, regs- >r10, regs- >r8, regs- >r9) ; } syscall_return_slowpath( regs ) ; } 上" />
0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

系統(tǒng)調(diào)用:用戶(hù)棧與內(nèi)核棧的切換(下)

麥辣雞腿堡 ? 來(lái)源:技術(shù)簡(jiǎn)說(shuō) ? 作者:董旭 ? 2023-07-31 11:29 ? 次閱讀

接下來(lái):call
do_syscall_64,進(jìn)入do_syscall_64函數(shù):

__visible void do_syscall_64(struct pt_regs *regs)
{
 struct thread_info *ti = current_thread_info();
 unsigned long nr = regs- >orig_ax;

 enter_from_user_mode();
 local_irq_enable();

 if (READ_ONCE(ti- >flags) & _TIF_WORK_SYSCALL_ENTRY)
  nr = syscall_trace_enter(regs);

 /*
  * NB: Native and x32 syscalls are dispatched from the same
  * table.  The only functional difference is the x32 bit in
  * regs- >orig_ax, which changes the behavior of some syscalls.
  */
 if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
  regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
   regs- >di, regs- >si, regs- >dx,
   regs- >r10, regs- >r8, regs- >r9);
 }

 syscall_return_slowpath(regs);
}

上述函數(shù)的主邏輯很簡(jiǎn)單:

1、 通過(guò)之前保存下來(lái)的pt_regs(往內(nèi)核棧中格式化壓入的),獲取用戶(hù)傳入的系統(tǒng)調(diào)用號(hào)nr,系統(tǒng)調(diào)用號(hào)保存在了regs->orig_ax:

unsigned long nr = regs- >orig_ax;

2、 通過(guò)系統(tǒng)調(diào)用號(hào)nr,執(zhí)行對(duì)應(yīng)的回調(diào)函數(shù),sys_call_table是函數(shù)指針數(shù)組,不同nr對(duì)應(yīng)不同系統(tǒng)調(diào)用對(duì)應(yīng)的函數(shù)。其中regx->di、regx->si、regs->dx、regs->r10、regs->r8、regs->r9分別是之前保存到內(nèi)核棧(以struct
pt_regs格式化)保存到pt_regs中的,對(duì)應(yīng)著用戶(hù)傳入該系統(tǒng)調(diào)用的參數(shù)1~6:

if (likely((nr & __SYSCALL_MASK) < NR_syscalls)) {
  regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
   regs- >di, regs- >si, regs- >dx,
   regs- >r10, regs- >r8, regs- >r9);
 }

以上就完成了用戶(hù)調(diào)用系統(tǒng)調(diào)用,并從用戶(hù)棧切換到內(nèi)核棧,并執(zhí)行到系統(tǒng)調(diào)用號(hào)對(duì)應(yīng)函數(shù)的過(guò)程。 具體的系統(tǒng)調(diào)用相關(guān)細(xì)節(jié)將在以后系統(tǒng)調(diào)用相關(guān)文章中分析。

系統(tǒng)調(diào)用-分析從內(nèi)核棧切換用戶(hù)棧

上面分析到了執(zhí)行系統(tǒng)調(diào)用對(duì)應(yīng)的函數(shù),如下所示,并將返回值保存在regs->ax中了

regs- >ax = sys_call_table[nr & __SYSCALL_MASK](
   regs- >di, regs- >si, regs- >dx,
   regs- >r10, regs- >r8, regs- >r9);

函數(shù)執(zhí)行到do_syscall_64->syscall_return_slowpath(regs),開(kāi)始為返回用戶(hù)態(tài)做準(zhǔn)備.

并最終回到系統(tǒng)調(diào)用 內(nèi)核SYSCALL 入口:ENTRY(entry_SYSCALL_64)->return_from_SYSCALL_64,繼續(xù)完成系統(tǒng)調(diào)用返回工作,并切換用戶(hù)棧與內(nèi)核棧,使用struct pt_regs恢復(fù)用戶(hù)態(tài)寄存器值。

總之

用戶(hù)棧——>內(nèi)核棧 cpu保存用戶(hù)當(dāng)前堆棧信息保存到內(nèi)核的棧中(恢復(fù)時(shí)用到),然后將cpu指向內(nèi)核堆棧,去執(zhí)行內(nèi)核代碼。完成用用戶(hù)棧到內(nèi)核棧轉(zhuǎn)換。

內(nèi)核?!?用戶(hù)棧 再切換到內(nèi)核堆棧前,將用戶(hù)堆棧信息壓入到內(nèi)核棧中,內(nèi)核函數(shù)執(zhí)行完回退棧幀,會(huì)將用戶(hù)的堆棧信息POP出棧,然后cpu堆棧寄存器就知道怎么回去了,返回的用戶(hù)程序中斷的地方繼續(xù)執(zhí)行。

聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 內(nèi)核
    +關(guān)注

    關(guān)注

    3

    文章

    1378

    瀏覽量

    40345
  • Linux
    +關(guān)注

    關(guān)注

    87

    文章

    11330

    瀏覽量

    209978
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    從 Linux 內(nèi)核的角度談線程和進(jìn)程

    1. 進(jìn)程 進(jìn)程是屬于用戶(hù)態(tài),和進(jìn)程 虛擬地址空間(Virtual Address Space) 密切相關(guān)。那我們先了解下什么是虛擬地址空間:在32位機(jī)器
    的頭像 發(fā)表于 09-25 15:23 ?2511次閱讀
    從 Linux <b class='flag-5'>內(nèi)核</b>的角度談線程<b class='flag-5'>棧</b>和進(jìn)程<b class='flag-5'>棧</b>

    C函數(shù)調(diào)用機(jī)制與幀原理詳解

    當(dāng)一個(gè)C函數(shù)被調(diào)用時(shí),函數(shù)的參數(shù)如何傳遞、堆棧指針如何變化、幀是如何被建立以及如何被消除的,一直缺乏系統(tǒng)性的理解,因此決定花時(shí)間學(xué)習(xí)函數(shù)調(diào)用
    發(fā)表于 06-08 10:49 ?1411次閱讀
    C函數(shù)<b class='flag-5'>調(diào)用</b>機(jī)制與<b class='flag-5'>棧</b>幀原理詳解

    操作系統(tǒng)為什么分內(nèi)核態(tài)和用戶(hù)態(tài)?這兩者如何切換

    操作系統(tǒng)為什么分內(nèi)核態(tài)和用戶(hù)態(tài),這兩者如何切換?進(jìn)程在地址空間會(huì)劃分為哪些區(qū)域?堆和有什么區(qū)別?
    發(fā)表于 07-23 09:01

    ARMv8的函數(shù)調(diào)用是什么意思?調(diào)用的內(nèi)存管理是怎樣的

    調(diào)用的函數(shù)稱(chēng)為非葉子函數(shù),而無(wú)調(diào)用的則稱(chēng)為葉子函數(shù)Q2:正常情況是否需要感知函數(shù)調(diào)用
    發(fā)表于 05-13 10:36

    用一個(gè)實(shí)例展示一Linux內(nèi)核幀的入和退過(guò)程

    1、Linux內(nèi)核調(diào)試方法總結(jié)之幀  幀  幀和指針可以說(shuō)是C語(yǔ)言的精髓。幀是一種特殊的數(shù)據(jù)結(jié)構(gòu),在C語(yǔ)言函數(shù)
    發(fā)表于 11-04 15:47

    一文詳解Linux內(nèi)核回溯與妙用

    網(wǎng)上或多或少都能找到回溯的一些文章,但是講的都并不完整,沒(méi)有將內(nèi)核回溯的功能用于實(shí)際的內(nèi)核、應(yīng)用程序調(diào)試,這是本篇文章的核心:盡可能引導(dǎo)讀者將
    的頭像 發(fā)表于 10-05 10:02 ?5421次閱讀
    一文詳解Linux<b class='flag-5'>內(nèi)核</b>的<b class='flag-5'>棧</b>回溯與妙用

    對(duì)Linux的進(jìn)程內(nèi)核的認(rèn)識(shí)

    在每一個(gè)進(jìn)程的生命周期中,必然會(huì)通過(guò)到系統(tǒng)調(diào)用陷入內(nèi)核。在執(zhí)行系統(tǒng)調(diào)用陷入內(nèi)核之后,這些
    發(fā)表于 05-12 08:53 ?628次閱讀
    對(duì)Linux的進(jìn)程<b class='flag-5'>內(nèi)核</b><b class='flag-5'>棧</b>的認(rèn)識(shí)

    帶你了解嵌入式C語(yǔ)言函數(shù)調(diào)用

    大家都知道函數(shù)調(diào)用是通過(guò)來(lái)實(shí)現(xiàn)的,而且知道在中存放著該函數(shù)的局部變量。但是對(duì)于的實(shí)現(xiàn)細(xì)節(jié)可能不一定清楚。
    發(fā)表于 07-12 17:08 ?2121次閱讀
    帶你了解嵌入式C語(yǔ)言函數(shù)<b class='flag-5'>調(diào)用</b><b class='flag-5'>棧</b>

    淺談鴻蒙內(nèi)核源碼的CPU四次換,寄存器改值

    本篇有相當(dāng)?shù)碾y度,涉及用戶(hù)內(nèi)核的兩輪切換,CPU四次換,寄存器改值,將圍繞下圖來(lái)說(shuō)明.?
    的頭像 發(fā)表于 04-28 16:56 ?1634次閱讀
    淺談鴻蒙<b class='flag-5'>內(nèi)核</b>源碼的CPU四次換<b class='flag-5'>棧</b>,寄存器改值

    淺談鴻蒙內(nèi)核源碼的

    上面的代碼和鴻蒙內(nèi)核方式一樣,都采用了遞減滿(mǎn)的方式, 什么是遞減滿(mǎn)?
    的頭像 發(fā)表于 04-24 11:21 ?1456次閱讀
    淺談鴻蒙<b class='flag-5'>內(nèi)核</b>源碼的<b class='flag-5'>棧</b>

    鴻蒙內(nèi)核源碼分析:用戶(hù)內(nèi)核的兩次切換

    這是系統(tǒng)調(diào)用的總?cè)肟?所有的系統(tǒng)調(diào)用都要跑這里要統(tǒng)一處理.通過(guò)系統(tǒng)號(hào)(保存在R7),找到注冊(cè)函數(shù)并回調(diào).完成
    的頭像 發(fā)表于 04-23 17:17 ?1936次閱讀
    鴻蒙<b class='flag-5'>內(nèi)核</b>源碼分析:<b class='flag-5'>用戶(hù)</b><b class='flag-5'>棧</b>和<b class='flag-5'>內(nèi)核</b><b class='flag-5'>棧</b>的兩次<b class='flag-5'>切換</b>

    嵌入式系統(tǒng)的變化

    函數(shù)調(diào)用是通過(guò)來(lái)實(shí)現(xiàn)的,而且知道在中存放著該函數(shù)的局部變量。但是,對(duì)于的實(shí)現(xiàn)細(xì)節(jié)可能不一定清楚。本文將介紹一在Linux平臺(tái)下函數(shù)
    的頭像 發(fā)表于 12-29 16:40 ?1131次閱讀
    嵌入式<b class='flag-5'>系統(tǒng)</b>中<b class='flag-5'>棧</b>的變化

    Linux中的進(jìn)程、線程、內(nèi)核以及中斷

    首先, (stack) 是一種串列形式的 數(shù)據(jù)結(jié)構(gòu)。這種數(shù)據(jù)結(jié)構(gòu)的特點(diǎn)是 后入先出 (LIFO, Last In First Out),數(shù)據(jù)只能在串列的一端 (稱(chēng)為:頂 top) 進(jìn)行 推入
    的頭像 發(fā)表于 05-14 09:30 ?735次閱讀
    Linux中的進(jìn)程<b class='flag-5'>棧</b>、線程<b class='flag-5'>棧</b>、<b class='flag-5'>內(nèi)核</b><b class='flag-5'>棧</b>以及中斷<b class='flag-5'>棧</b>

    系統(tǒng)調(diào)用用戶(hù)內(nèi)核切換(上)

    當(dāng)發(fā)生系統(tǒng)調(diào)用、產(chǎn)生異常,外設(shè)發(fā)生中斷等事件時(shí),會(huì)發(fā)生用戶(hù)內(nèi)核之間的
    的頭像 發(fā)表于 07-31 11:27 ?900次閱讀
    <b class='flag-5'>系統(tǒng)</b><b class='flag-5'>調(diào)用</b>:<b class='flag-5'>用戶(hù)</b><b class='flag-5'>棧</b>與<b class='flag-5'>內(nèi)核</b><b class='flag-5'>棧</b>的<b class='flag-5'>切換</b>(上)

    linux中的進(jìn)程,線程,內(nèi)核的區(qū)別

    大多數(shù)的處理器架構(gòu),都有實(shí)現(xiàn)硬件。有專(zhuān)門(mén)的指針寄存器,以及特定的硬件指令來(lái)完成 入/出 的操作。例如在 ARM 架構(gòu)上,R13 (SP) 指針是堆棧指針寄存器,而 PUSH 是
    發(fā)表于 08-18 10:57 ?531次閱讀
    linux中的進(jìn)程<b class='flag-5'>棧</b>,線程<b class='flag-5'>棧</b>,<b class='flag-5'>內(nèi)核</b><b class='flag-5'>棧</b>的區(qū)別