精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

淺談鴻蒙內核源碼的CPU四次換棧,寄存器改值

鴻蒙系統HarmonyOS ? 來源:my.oschina ? 作者:鴻蒙內核源碼分析 ? 2021-04-28 16:56 ? 次閱讀

本篇有相當的難度,涉及用戶棧和內核棧的兩輪切換,CPU四次換棧,寄存器改值,將圍繞下圖來說明.

o4YBAGCJIoaASEOiAAFXah8_bJQ641.png

解讀

為本篇理解方便,把圖做簡化標簽說明:

user:用戶空間

kernel:內核空間

source(...):源函數

sighandle(...):信號處理函數,

syscall(...):系統調用,參數為系統調用號,如sigreturn,N(表任意)

user.source():表示在用戶空間運行的源函數

系列篇已多次說過,用戶態的任務有兩個運行棧,一個是用戶棧,一個是內核棧.??臻g分別來自用戶空間和內核空間.兩種空間是有嚴格的地址劃分的,通過虛擬地址的大小就能判斷出是用戶空間還是內核空間.系統調用本質上是軟中斷,它使CPU執行指令的場地由用戶棧變成內核棧.怎么變的并不復雜,就是改變(sp和cpsr寄存器的值).sp指向哪個棧就代表在哪個棧運行, 當cpu在用戶棧運行時是不能訪問內核空間的,但內核態任務可以訪問整個空間,而且內核態任務沒有用戶棧.

理解了上面的說明,再來說下正常系統調用流程是這樣的: user.source() -> kernel.syscall(N) - > user.source() ,想要回到user.source()繼續運行,就必須保存用戶?,F場各寄存器的值.這些值保存在內核棧中,恢復也是從內核?;謴?

信號消費的過程的上圖可簡化表示為: user.source() -> kernel.syscall(N) ->user.sighandle() ->kernel.syscall(sigreturn) -> user.source() 在原本要回到user.source()的中間插入了信號處理函數的調用. 這正是本篇要通過代碼來說清楚的核心問題.

順著這個思路可以推到以下幾點,實際也是這么做的:

kernel.syscall(N) 中必須要再次保存user.source()的上下文sig_switch_context,為何已經保存了一次還要再保存一次?

因為第一次是保存在內核棧中,而內核棧這部分數據會因回到用戶態user.sighandle()運行而被恢復現場出棧了.保存現場/恢復現場是成雙出隊的好基友,注意有些文章說會把整個內核棧清空,這是不對的.

第二次保存在任務結構體中,任務來源于任務池,是內核全局變量,常駐內存的.兩次保存的都是user.source()運行時現場信息,再回顧下相關的結構體.關鍵是sig_switch_context

typedef struct {
    // ...
    sig_cb  sig;//信號控制塊,用于異步通信
} LosTaskCB;
typedef struct {//信號控制塊(描述符)
    sigset_t sigFlag;		//不屏蔽的信號集
    sigset_t sigPendFlag;	//信號阻塞標簽集,記錄那些信號來過,任務依然阻塞的集合.即:這些信號不能喚醒任務
    sigset_t sigprocmask; /* Signals that are blocked            */	//任務屏蔽了哪些信號
    sq_queue_t sigactionq;	//信號捕捉隊列					
    LOS_DL_LIST waitList;	//等待鏈表,上面掛的是等待信號到來的任務, 請查找 OsTaskWait(&sigcb->waitList, timeout, TRUE)	理解						
    sigset_t sigwaitmask; /* Waiting for pending signals         */	//任務在等待哪些信號的到來
    siginfo_t sigunbinfo; /* Signal info when task unblocked     */	//任務解鎖時的信號信息
    sig_switch_context context;	//信號切換上下文, 用于保存切換現場, 比如發生系統調用時的返回,涉及同一個任務的兩個棧進行切換			
} sig_cb;

還必須要改變原有PC/R0/R1寄存器的值.想要執行user.sighandle(),PC寄存器就必須指向它,而R0,R1就是它的參數.

信號處理完成后須回到內核態,怎么再次陷入內核態? 答案是:__NR_sigreturn,這也是個系統調用.回來后還原sig_switch_context,即還原user.source()被打斷時SP/PC等寄存器的值,使其跳回到用戶棧從user.source()的被打斷處繼續執行.

有了這三個推論,再理解下面的代碼就是吹灰之力了,涉及三個關鍵函數OsArmA32SyscallHandle,OsSaveSignalContext,OsRestorSignalContext本篇一一解讀,徹底挖透.先看信號上下文結構體sig_switch_context.

sig_switch_context

//任務中斷上下文
#define TASK_IRQ_CONTEXT \
        unsigned int R0;     \
        unsigned int R1;     \
        unsigned int R2;     \
        unsigned int R3;     \
        unsigned int R12;    \
        unsigned int USP;    \
        unsigned int ULR;    \
        unsigned int CPSR;   \
        unsigned int PC;

typedef struct {//信號切換上下文
    TASK_IRQ_CONTEXT
    unsigned int R7;	//存放系統調用的ID
    unsigned int count;	//記錄是否保存了信號上下文
} sig_switch_context;

保存user.source()現場的結構體,USP,ULR代表用戶棧指針和返回地址.

CPSR寄存器用于設置CPU的工作模式,CPU有7種工作模式,具體可前往翻看
v36.xx (工作模式篇) | cpu是韋小寶,有哪七個老婆?談論的用戶態(usr普通用戶)和內核態(sys超級用戶)對應的只是其中的兩種.二者都共用相同的寄存器.還原它就是告訴CPU內核已切到普通用戶模式運行.

其他寄存器沒有保存的原因是系統調用不會用到它們,所以不需要保存.

R7是在系統調用發生時用于記錄系統調用號,在信號處理過程中,R0將獲得信號編號,作為user.sighandle()的第一個參數.

count記錄是否保存了信號上下文

OsArmA32SyscallHandle 系統調用總入口

/* The SYSCALL ID is in R7 on entry.  Parameters follow in R0..R6 */
/******************************************************************
由匯編調用,見于 los_hw_exc.s    / BLX    OsArmA32SyscallHandle
SYSCALL是產生系統調用時觸發的信號,R7寄存器存放具體的系統調用ID,也叫系統調用號
regs:參數就是所有寄存器
注意:本函數在用戶態和內核態下都可能被調用到
//MOV     R0, SP @獲取SP值,R0將作為OsArmA32SyscallHandle的參數
******************************************************************/
LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)
{
    UINT32 ret;
    UINT8 nArgs;
    UINTPTR handle;
    UINT32 cmd = regs[REG_R7];//C7寄存器記錄了觸發了具體哪個系統調用
	
    if (cmd >= SYS_CALL_NUM) {//系統調用的總數
        PRINT_ERR("Syscall ID: error %d !!!\n", cmd);
        return regs;
    }
	//用戶進程信號處理函數完成后的系統調用 svc 119 #__NR_sigreturn
    if (cmd == __NR_sigreturn) {
        OsRestorSignalContext(regs);//恢復信號上下文,回到用戶棧運行.
        return regs;
    }

    handle = g_syscallHandle[cmd];//拿到系統調用的注冊函數,類似 SysRead 
    nArgs = g_syscallNArgs[cmd / NARG_PER_BYTE]; /* 4bit per nargs */
    nArgs = (cmd & 1) ? (nArgs >> NARG_BITS) : (nArgs & NARG_MASK);//獲取參數個數
    if ((handle == 0) || (nArgs > ARG_NUM_7)) {//系統調用必須有參數且參數不能大于8個
        PRINT_ERR("Unsupport syscall ID: %d nArgs: %d\n", cmd, nArgs);
        regs[REG_R0] = -ENOSYS;
        return regs;
    }
	//regs[0-6] 記錄系統調用的參數,這也是由R7寄存器保存系統調用號的原因
    switch (nArgs) {//參數的個數 
        case ARG_NUM_0:
        case ARG_NUM_1:
            ret = (*(SyscallFun1)handle)(regs[REG_R0]);//執行系統調用,類似 SysUnlink(pathname);
            break;
        case ARG_NUM_2://如何是兩個參數的系統調用,這里傳三個參數也沒有問題,因被調用函數不會去取用R2值
        case ARG_NUM_3:
            ret = (*(SyscallFun3)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2]);//類似 SysExecve(fileName, argv, envp);
            break;
        case ARG_NUM_4:
        case ARG_NUM_5:
            ret = (*(SyscallFun5)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
                                         regs[REG_R4]);
            break;
        default:	//7個參數的情況
            ret = (*(SyscallFun7)handle)(regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
                                         regs[REG_R4], regs[REG_R5], regs[REG_R6]);
    }

    regs[REG_R0] = ret;//R0保存系統調用返回值
    OsSaveSignalContext(regs);//如果有信號要處理,將改寫pc,r0,r1寄存器,改變返回正常用戶態路徑,而先去執行信號處理程序.

    /* Return the last value of curent_regs.  This supports context switches on return from the exception.
     * That capability is only used with the SYS_context_switch system call.
     */
    return regs;//返回寄存器的值
}

解讀

這是系統調用的總入口,所有的系統調用都要跑這里要統一處理.通過系統號(保存在R7),找到注冊函數并回調.完成系統調用過程.

關于系統調用可查看v37.xx (系統調用篇) | 系統調用到底經歷了什么本篇不詳細說系統調用過程,只說跟信號相關的部分.

OsArmA32SyscallHandle總體理解起來是被信號的保存和還原兩個函數給包夾了.注意要在運行過程中去理解調用兩個函數的過程,對于同一個任務來說,一定是先執行OsSaveSignalContext,第二次進入OsArmA32SyscallHandle后再執行OsRestorSignalContext.

看OsSaveSignalContext,由它負責保存user.source() 的上下文,其中改變了sp,r0/r1寄存器值,切到信號處理函數user.sighandle()運行.

在函數的開頭,碰到系統調用號__NR_sigreturn,直接恢復信號上下文就退出了,因為這是要切回user.source()繼續運行的操作.

//用戶進程信號處理函數完成后的系統調用 svc 119 #__NR_sigreturn
if (cmd == __NR_sigreturn) {
    OsRestorSignalContext(regs);//恢復信號上下文,回到用戶棧運行.
    return regs;
}

OsSaveSignalContext 保存信號上下文

有了上面的鋪墊,就不難理解這個函數的作用.

/**********************************************
產生系統調用時,也就是軟中斷時,保存用戶棧寄存器現場信息
改寫PC寄存器的值
**********************************************/
void OsSaveSignalContext(unsigned int *sp)
{
    UINTPTR sigHandler;
    UINT32 intSave;
    LosTaskCB *task = NULL;
    LosProcessCB *process = NULL;
    sig_cb *sigcb = NULL;
    unsigned long cpsr;

    OS_RETURN_IF_VOID(sp == NULL);
    cpsr = OS_SYSCALL_GET_CPSR(sp);//獲取系統調用時的 CPSR值
    OS_RETURN_IF_VOID(((cpsr & CPSR_MASK_MODE) != CPSR_USER_MODE));//必須工作在CPU的用戶模式下,注意CPSR_USER_MODE(cpu層面)和OS_USER_MODE(系統層面)是兩碼事.
    SCHEDULER_LOCK(intSave);//如有不明白前往 https://my.oschina.net/weharmony 翻看工作模式/信號分發/信號處理篇
    task = OsCurrTaskGet();
    process = OsCurrProcessGet();
    sigcb = &task->sig;//獲取任務的信號控制塊
	//1.未保存任務上下文任務
	//2.任何的信號標簽集不為空或者進程有信號要處理
    if ((sigcb->context.count == 0) && ((sigcb->sigFlag != 0) || (process->sigShare != 0))) {
        sigHandler = OsGetSigHandler();//獲取信號處理函數
        if (sigHandler == 0) {//信號沒有注冊
            sigcb->sigFlag = 0;
            process->sigShare = 0;
            SCHEDULER_UNLOCK(intSave);
            PRINT_ERR("The signal processing function for the current process pid =%d is NULL!\n", task->processID);
            return;
        }
        /* One pthread do the share signal */ 
        sigcb->sigFlag |= process->sigShare;//擴展任務的信號標簽集
        unsigned int signo = (unsigned int)FindFirstSetedBit(sigcb->sigFlag) + 1;
        OsProcessExitCodeSignalSet(process, signo);//設置進程退出信號
        sigcb->context.CPSR = cpsr;		//保存狀態寄存器
        sigcb->context.PC = sp[REG_PC]; //獲取被打斷現場寄存器的值
        sigcb->context.USP = sp[REG_SP];//用戶棧頂位置,以便能從內核棧切回用戶棧
        sigcb->context.ULR = sp[REG_LR];//用戶棧返回地址
        sigcb->context.R0 = sp[REG_R0];	//系統調用的返回值
        sigcb->context.R1 = sp[REG_R1];
        sigcb->context.R2 = sp[REG_R2];
        sigcb->context.R3 = sp[REG_R3]; 
        sigcb->context.R7 = sp[REG_R7];//為何參數不用傳R7,是因為系統調用發生時 R7始終保存的是系統調用號.
        sigcb->context.R12 = sp[REG_R12];//詳見 https://my.oschina.net/weharmony/blog/4967613
        sp[REG_PC] = sigHandler;//指定信號執行函數,注意此處改變保存任務上下文中PC寄存器的值,恢復上下文時將執行這個函數.
        sp[REG_R0] = signo;		//參數1,信號ID
        sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); //參數2
        /* sig No bits 00000100 present sig No 3, but  1<< 3 = 00001000, so signo needs minus 1 */
        sigcb->sigFlag ^= 1ULL << (signo - 1);
        sigcb->context.count++;	//代表已保存
    }
    SCHEDULER_UNLOCK(intSave);
}

解讀

先是判斷執行條件,確實是有信號需要處理,有處理函數.自定義處理函數是由用戶進程安裝進來的,所有進程旗下的任務都共用,參數就是信號signo,注意可不是系統調用號,有區別的.信號編號長這樣.

#define SIGHUP    1	//終端掛起或者控制進程終止
#define SIGINT    2	//鍵盤中斷(ctrl + c)
#define SIGQUIT   3	//鍵盤的退出鍵被按下
#define SIGILL    4	//非法指令
#define SIGTRAP   5	//跟蹤陷阱(trace trap),啟動進程,跟蹤代碼的執行
#define SIGABRT   6	//由abort(3)發出的退出指令
#define SIGIOT    SIGABRT //abort發出的信號
#define SIGBUS    7	//總線錯誤 
#define SIGFPE    8	//浮點異常
#define SIGKILL   9	//常用的命令 kill 9 123 | 不能被忽略、處理和阻塞

系統調用號長這樣,是不是看到一些很熟悉的函數.

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
#define __NR_read 3
#define __NR_write 4
#define __NR_open 5
#define __NR_close 6
#define __NR_waitpid 7
#define __NR_creat 8
#define __NR_link 9
#define __NR_unlink 10
#define __NR_execve 11
#define __NR_chdir 12
#define __NR_time 13
#define __NR_mknod 14
#define __NR_chmod 15
#define __NR_lchown 16
#define __NR_break 17

最后是最最最關鍵的代碼,改變pc寄存器的值,此值一變,在_osExceptSwiHdl中恢復上下文后,cpu跳到用戶空間的代碼段 user.sighandle(R0,R1) 開始執行,即執行信號處理函數.

sp[REG_PC] = sigHandler;//指定信號執行函數,注意此處改變保存任務上下文中PC寄存器的值,恢復上下文時將執行這個函數.
sp[REG_R0] = signo;		//參數1,信號ID
sp[REG_R1] = (unsigned int)(UINTPTR)(sigcb->sigunbinfo.si_value.sival_ptr); //參數2

OsRestorSignalContext 恢復信號上下文

/****************************************************
恢復信號上下文,由系統調用之__NR_sigreturn產生,這是一個內部產生的系統調用.
為什么要恢復呢?
因為系統調用的執行由任務內核態完成,使用的棧也是內核棧,CPU相關寄存器記錄的都是內核棧的內容,
而系統調用完成后,需返回任務的用戶棧執行,這時需將CPU各寄存器回到用戶態現場
所以函數的功能就變成了還原寄存器的值
****************************************************/
void OsRestorSignalContext(unsigned int *sp)
{
    LosTaskCB *task = NULL; /* Do not adjust this statement */
    LosProcessCB *process = NULL;
    sig_cb *sigcb = NULL;
    UINT32 intSave;

    SCHEDULER_LOCK(intSave);
    task = OsCurrTaskGet();
    sigcb = &task->sig;//獲取當前任務信號控制塊

    if (sigcb->context.count != 1) {//必須之前保存過,才能被恢復
        SCHEDULER_UNLOCK(intSave);
        PRINT_ERR("sig error count : %d\n", sigcb->context.count);
        return;
    }

    process = OsCurrProcessGet();//獲取當前進程
    sp[REG_PC] = sigcb->context.PC;//指令寄存器
    OS_SYSCALL_SET_CPSR(sp, sigcb->context.CPSR);//重置程序狀態寄存器
    sp[REG_SP] = sigcb->context.USP;//用戶棧堆棧指針, USP指的是 用戶態的堆棧,即將回到用戶棧繼續運行
    sp[REG_LR] = sigcb->context.ULR;//返回用戶棧代碼執行位置
    sp[REG_R0] = sigcb->context.R0;
    sp[REG_R1] = sigcb->context.R1;
    sp[REG_R2] = sigcb->context.R2;
    sp[REG_R3] = sigcb->context.R3;
    sp[REG_R7] = sigcb->context.R7;
    sp[REG_R12] = sigcb->context.R12;
    sigcb->context.count--;	//信號上下文的數量回到減少
    process->sigShare = 0;	//回到用戶態,信號共享清0
    OsProcessExitCodeSignalClear(process);//清空進程退出碼
    SCHEDULER_UNLOCK(intSave);
}

解讀

在信號處理函數完成之后,內核會觸發一個__NR_sigreturn的系統調用,又陷入內核態,回到了OsArmA32SyscallHandle.

恢復的過程很簡單,把之前保存的信號上下文恢復到內核棧sp開始位置,數據在棧中的保存順序可查看 用棧方式篇 ,最重要的看這幾句.

sp[REG_PC] = sigcb->context.PC;//指令寄存器
sp[REG_SP] = sigcb->context.USP;//用戶棧堆棧指針, USP指的是 用戶態的堆棧,即將回到用戶棧繼續運行
sp[REG_LR] = sigcb->context.ULR;//返回用戶棧代碼執行位置

注意這里還不是真正的切換上下文,只是改變內核棧中現有的數據.這些數據將還原給寄存器.USP和ULR指向的是用戶棧的位置.一旦PC,USP,ULR從棧中彈出賦給寄存器.才真正完成了內核棧到用戶棧的切換.回到了user.source()繼續運行.

真正的切換匯編代碼如下,都已添加注釋,在保存和恢復上下文中夾著OsArmA32SyscallHandle

@ Description: Software interrupt exception handler
_osExceptSwiHdl: @軟中斷異常處理,注意此時已在內核棧運行
@保存任務上下文(TaskContext) 開始... 一定要對照TaskContext來理解
SUB     SP, SP, #(4 * 16)	@先申請16個??臻g單元用于處理本次軟中斷
STMIA   SP, {R0-R12}		@TaskContext.R[GEN_REGS_NUM] STMIA從左到右執行,先放R0 .. R12
MRS     R3, SPSR			@讀取本模式下的SPSR值
MOV     R4, LR				@保存回跳寄存器LR

AND     R1, R3, #CPSR_MASK_MODE                          @ Interrupted mode 獲取中斷模式
CMP     R1, #CPSR_USER_MODE                              @ User mode	是否為用戶模式
BNE     OsKernelSVCHandler                               @ Branch if not user mode 非用戶模式下跳轉
@ 當為用戶模式時,獲取SP和LR寄出去值
@ we enter from user mode, we need get the values of  USER mode r13(sp) and r14(lr).
@ stmia with ^ will return the user mode registers (provided that r15 is not in the register list).
MOV     R0, SP											 @獲取SP值,R0將作為OsArmA32SyscallHandle的參數
STMFD   SP!, {R3}                                        @ Save the CPSR 入棧保存CPSR值 => TaskContext.regPSR
ADD     R3, SP, #(4 * 17)                                @ Offset to pc/cpsr storage 跳到PC/CPSR存儲位置
STMFD   R3!, {R4}                                        @ Save the CPSR and r15(pc) 保存LR寄存器 => TaskContext.PC
STMFD   R3, {R13, R14}^                                  @ Save user mode r13(sp) and r14(lr) 從右向左 保存 => TaskContext.LR和SP
SUB     SP, SP, #4										 @ => TaskContext.resved
PUSH_FPU_REGS R1	@保存中斷模式(用戶模式)											
@保存任務上下文(TaskContext) 結束
MOV     FP, #0                                           @ Init frame pointer
CPSIE   I	@開中斷,表明在系統調用期間可響應中斷
BLX     OsArmA32SyscallHandle	/*交給C語言處理系統調用,參數為R0,指向TaskContext的開始位置*/
CPSID   I	@執行后續指令前必須先關中斷
@恢復任務上下文(TaskContext) 開始
POP_FPU_REGS R1											 @彈出FPU值給R1
ADD     SP, SP,#4										 @ 定位到保存舊SPSR值的位置
LDMFD   SP!, {R3}                                        @ Fetch the return SPSR 彈出舊SPSR值
MSR     SPSR_cxsf, R3                                    @ Set the return mode SPSR 恢復該模式下的SPSR值

@ we are leaving to user mode, we need to restore the values of USER mode r13(sp) and r14(lr).
@ ldmia with ^ will return the user mode registers (provided that r15 is not in the register list)

LDMFD   SP!, {R0-R12}									 @恢復R0-R12寄存器
LDMFD   SP, {R13, R14}^                                  @ Restore user mode R13/R14 恢復用戶模式的R13/R14寄存器
ADD     SP, SP, #(2 * 4)								 @定位到保存舊PC值的位置
LDMFD   SP!, {PC}^                                       @ Return to user 切回用戶模式運行
@恢復任務上下文(TaskContext) 結束

編輯:hfy

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5317

    瀏覽量

    120010
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10825

    瀏覽量

    211155
  • 信號處理
    +關注

    關注

    48

    文章

    1000

    瀏覽量

    103201
收藏 人收藏

    評論

    相關推薦

    解析CPU中的寄存器

    8位寄存器在16位寄存器中,而16位寄存器在32位寄存器中。
    發表于 09-19 10:10 ?3975次閱讀

    淺析從寄存器到用戶態與內核

    寄存器CPU內部重要的組成部分,寄存器內部由N個觸發組成,每個觸發可以保存1位二進制數,所以16位
    的頭像 發表于 01-30 15:28 ?2644次閱讀

    寄存器變量

    C語言中使用關鍵字register來聲明局部變量為寄存器變量。寄存器變量的會被存放在CPU寄存器中,每當需要使用它們時,
    發表于 06-03 10:13 ?2340次閱讀

    鴻蒙內核源碼分析寄存器的本質

    寄存器的本質 寄存器從大一的計算機組成原理就開始聽到它,感覺很神秘,如夢如霧多年.揭開本質后才發現,寄存器就是一個32位的存儲空間,一個int變量而已,但它的厲害之處在于極高頻率的使用,讓人不敢相信
    的頭像 發表于 04-26 14:51 ?2445次閱讀
    <b class='flag-5'>鴻蒙</b><b class='flag-5'>內核</b><b class='flag-5'>源碼</b>分析<b class='flag-5'>寄存器</b>的本質

    淺談鴻蒙內核源碼

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

    華為鴻蒙系統內核源碼分析上冊

    鴻蒙內核源碼注釋中文版【 Gitee倉】給 Harmoηy○S源碼逐行加上中文注解,詳細闡述設計細節,助你快速精讀 Harmonyos內核源碼
    發表于 04-09 14:40 ?17次下載

    深度剖析ARM內核寄存器及基本匯編語言1

    M3/M4內核寄存器 * 1.2 A7內核寄存器 * 1.3 ARM中的PC指針的 * 二、ARM匯編語言
    的頭像 發表于 04-24 09:59 ?943次閱讀
    深度剖析ARM<b class='flag-5'>內核</b><b class='flag-5'>寄存器</b>及基本匯編語言1

    深度剖析ARM內核寄存器及基本匯編語言3

    M3/M4內核寄存器 * 1.2 A7內核寄存器 * 1.3 ARM中的PC指針的 * 二、ARM匯編語言
    的頭像 發表于 04-24 10:01 ?1186次閱讀
    深度剖析ARM<b class='flag-5'>內核</b><b class='flag-5'>寄存器</b>及基本匯編語言3

    基于DUT內部寄存器的鏡像

    寄存器模型保持著DUT內部寄存器的 鏡像(mirror) 。 鏡像不能保證是正確的,因為寄存器模型只能感知到對這些
    的頭像 發表于 06-24 12:02 ?848次閱讀

    linux中的進程,線程,內核的區別

    大多數的處理架構,都有實現硬件。有專門的指針寄存器,以及特定的硬件指令來完成 入/出
    發表于 08-18 10:57 ?458次閱讀
    linux中的進程<b class='flag-5'>棧</b>,線程<b class='flag-5'>棧</b>,<b class='flag-5'>內核</b><b class='flag-5'>棧</b>的區別

    如何理解 RAMECC FAR 寄存器

    如何理解 RAMECC FAR 寄存器
    的頭像 發表于 10-19 18:19 ?627次閱讀
    如何理解 RAMECC FAR <b class='flag-5'>寄存器</b>的<b class='flag-5'>值</b>

    CPU的6個主要寄存器

    CPU寄存器是中央處理內的組成部分,是有限存貯容量的高速存貯部件。寄存器CPU內部的元件,包括通用
    的頭像 發表于 02-03 15:15 ?3904次閱讀

    干貨滿滿:ARM的內核寄存器講解

    內核寄存器與外設寄存器內核寄存器與外設寄存器是完全不同的概念。
    發表于 04-17 11:47 ?2967次閱讀
    干貨滿滿:ARM的<b class='flag-5'>內核</b><b class='flag-5'>寄存器</b>講解

    寄存器分為基本寄存器和什么兩種

    寄存器是計算機中用于存儲數據的高速存儲單元,它們是CPU內部的重要組成部分。寄存器可以分為基本寄存器和擴展寄存器兩種類型。 一、基本
    的頭像 發表于 07-12 10:31 ?1128次閱讀

    詳解寄存器模型鏡像

    DUT的配置寄存器是實際,reg_model有鏡像、期望的概念。
    的頭像 發表于 10-23 09:43 ?186次閱讀
    詳解<b class='flag-5'>寄存器</b>模型鏡像<b class='flag-5'>值</b>