注解0号进程是如何创建的?

    百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
    https://my.oschina.net/weharmony
上级 eaafbccc
......@@ -86,7 +86,7 @@ SPSR(saved program status register)程序状态保存寄存器.
******************************************************************************/
#define CPSR_INT_DISABLE 0xC0 /* Disable both FIQ and IRQ */ //禁止IRQ和FIQ中断,因为0xC0 = 0x80 + 0x40
#define CPSR_IRQ_DISABLE 0x80 /* IRQ disabled when =1 */ //禁止IRQ 中断
#define CPSR_FIQ_DISABLE 0x40 /* FIQ disabled when =1 */ //禁止 FIQ中断
#define CPSR_FIQ_DISABLE 0x40 /* FIQ disabled when =1 */ //禁止FIQ中断
#define CPSR_THUMB_ENABLE 0x20 /* Thumb mode when =1 */ //使能Thumb模式 1:CPU处于Thumb状态, 0:CPU处于ARM状态
#define CPSR_USER_MODE 0x10 //用户模式,除了用户模式,其余模式也叫特权模式,特权模式中除了系统模式以外的其余5种模式称为异常模式;
#define CPSR_FIQ_MODE 0x11 //快中断模式 用于高速数据传输或通道处理
......
......@@ -131,17 +131,20 @@ STATIC INLINE VOID *ArchCurrTaskGet(VOID)
{
return (VOID *)(UINTPTR)ARM_SYSREG_READ(TPIDRPRW);//读c13寄存器
}
//设置当前task ID
STATIC INLINE VOID ArchCurrTaskSet(VOID *val)
{
ARM_SYSREG_WRITE(TPIDRPRW, (UINT32)(UINTPTR)val);
}
//向协处理器写入用户态任务ID TPIDRURO 仅用于用户态
STATIC INLINE VOID ArchCurrUserTaskSet(UINTPTR val)
{
ARM_SYSREG_WRITE(TPIDRURO, (UINT32)val);
}
//https://www.keil.com/pack/doc/cmsis/Core_A/html/group__CMSIS__MPIDR.html
/*
* https://www.keil.com/pack/doc/cmsis/Core_A/html/group__CMSIS__MPIDR.html
* 在多处理器系统中,MPIDR为调度目的提供额外的处理器标识机制,并指示实现是否包括多处理器扩展。
*/
STATIC INLINE UINT32 ArchCurrCpuid(VOID)
{
#if (LOSCFG_KERNEL_SMP == YES)//CPU多核情况
......@@ -163,7 +166,7 @@ STATIC INLINE UINT32 OsMainIDGet(VOID)
/* CPU interrupt mask handle implementation */ //CPU中断掩码句柄实现
#if LOSCFG_ARM_ARCH >= 6
//禁止中断
STATIC INLINE UINT32 ArchIntLock(VOID)
{
UINT32 intSave;
......@@ -175,7 +178,7 @@ STATIC INLINE UINT32 ArchIntLock(VOID)
: "memory");
return intSave;
}
//恢复中断
STATIC INLINE UINT32 ArchIntUnlock(VOID)
{
UINT32 intSave;
......
......@@ -59,8 +59,8 @@ typedef struct { //参考OsTaskSchedule来理解
UINT32 resved; /* It's stack 8 aligned */
UINT32 regPSR;
UINT32 R[GEN_REGS_NUM]; /* R0-R12 */
UINT32 SP; /* R13 */
UINT32 LR; /* R14 */
UINT32 SP; /* R13 */ //保存用户空间SP
UINT32 LR; /* R14 */ //保存用户空间LR
UINT32 PC; /* R15 */
} TaskContext;
......
......@@ -623,8 +623,8 @@ STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end
if (g_excFromUserMode[ArchCurrCpuid()] == TRUE) {//当前CPU在用户态执行发生异常
taskCB = OsCurrTaskGet();
stackStart = taskCB->userMapBase;
stackEnd = taskCB->userMapBase + taskCB->userMapSize;
stackStart = taskCB->userMapBase;//用户态栈基地址,即用户态栈顶
stackEnd = taskCB->userMapBase + taskCB->userMapSize;//用户态栈结束地址
if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
found = TRUE;
goto FOUND;
......@@ -632,22 +632,22 @@ STATIC INLINE BOOL FindSuitableStack(UINTPTR regFP, UINTPTR *start, UINTPTR *end
return found;
}
/* Search in the task stacks */
/* Search in the task stacks *///找任务的内核态栈
for (index = 0; index < g_taskMaxNum; index++) {
taskCB = &g_taskCBArray[index];
if (OsTaskIsUnused(taskCB)) {
continue;
}
stackStart = taskCB->topOfStack;
stackEnd = taskCB->topOfStack + taskCB->stackSize;
stackStart = taskCB->topOfStack;//内核态栈顶
stackEnd = taskCB->topOfStack + taskCB->stackSize;//内核态栈底
if (IsValidFP(regFP, stackStart, stackEnd, &kvaddr) == TRUE) {
found = TRUE;
goto FOUND;
}
}
/* Search in the exc stacks */
/* Search in the exc stacks *///从异常栈中找
for (index = 0; index < sizeof(g_excStack) / sizeof(StackInfo); index++) {
stack = &g_excStack[index];
stackStart = (UINTPTR)stack->stackTop;
......
......@@ -141,7 +141,7 @@ LITE_OS_SEC_TEXT_INIT VOID OsUserTaskStackInit(TaskContext *context, TSK_ENTRY_F
#else
context->regPSR = PSR_MODE_USR_ARM;//工作模式:用户模式 + 工作状态:arm
#endif
context->R[0] = stack;//因为要回到用户态空间运行,所以要作为参数传回SP值
context->R[0] = stack;//将用户态栈指针保存到上下文R0处
context->SP = TRUNCATE(stack, LOSCFG_STACK_POINT_ALIGN_SIZE);//改变 上下文的SP值,指向用户栈空间
context->LR = 0;//保存子程序返回地址 例如 a call b ,在b中保存 a地址
context->PC = (UINTPTR)taskEntry;//入口函数,由外部传入,由上层应用指定,固然每个都不一样.
......
......@@ -178,9 +178,9 @@ STMDA(完成操作而后地址递减)、STMED(空递减堆栈)。
*/
@ Description: Software interrupt exception handler
_osExceptSwiHdl: @软中断异常处理
_osExceptSwiHdl: @软中断异常处理,注意此时已在内核栈运行
@保存任务上下文(TaskContext) 开始... 一定要对照TaskContext来理解
SUB SP, SP, #(4 * 16) @先申请16个栈空间用于处理本次软中断
SUB SP, SP, #(4 * 16) @先申请16个栈空间单元用于处理本次软中断
STMIA SP, {R0-R12} @TaskContext.R[GEN_REGS_NUM] STMIA从左到右执行,先放R0 .. R12
MRS R3, SPSR @读取本模式下的SPSR
MOV R4, LR @保存回跳寄存器LR
......@@ -201,7 +201,7 @@ _osExceptSwiHdl: @软中断异常处理
@保存任务上下文(TaskContext) 结束
MOV FP, #0 @ Init frame pointer
CPSIE I @开中断,表明在系统调用期间可响应中断
BLX OsArmA32SyscallHandle /*交给C语言处理系统调用*/
BLX OsArmA32SyscallHandle /*交给C语言处理系统调用,参数为R0,指向TaskContext的开始位置*/
CPSID I @执行后续指令前必须先关中断
@恢复任务上下文(TaskContext) 开始
POP_FPU_REGS R1 @弹出FP值给R1
......
......@@ -525,16 +525,19 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsProcessInit(VOID)
LOS_ListInit(&g_processRecyleList);//进程回收链表初始化,回收完成后进入g_freeProcess等待再次被申请使用
for (index = 0; index < g_processMaxNum; index++) {//进程池循环创建
g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum]赋值
g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum-1]赋值
g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;// 默认都是白纸一张,贴上未使用标签
LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);//注意g_freeProcess挂的是pendList节点,所以使用要通过OS_PCB_FROM_PENDLIST找到进程实体.
}
g_userInitProcess = 1; /* 1: The root process ID of the user-mode process is fixed at 1 *///用户态的根进程
LOS_ListDelete(&g_processCBArray[g_userInitProcess].pendList);// 清空g_userInitProcess pend链表
LOS_ListDelete(&g_processCBArray[g_userInitProcess].pendList);// 将1号进程从空闲链表上摘出去
g_kernelInitProcess = 2; /* 2: The root process ID of the kernel-mode process is fixed at 2 *///内核态的根进程
LOS_ListDelete(&g_processCBArray[g_kernelInitProcess].pendList);// 清空g_kernelInitProcess pend链表
LOS_ListDelete(&g_processCBArray[g_kernelInitProcess].pendList);// 将2号进程从空闲链表上摘出去
//注意:这波骚操作之后,g_freeProcess链表上还有,0,3,4,...g_processMaxNum-1号进程.创建进程是从g_freeProcess上申请
//即下次申请到的将是0号进程,而 OsCreateIdleProcess 将占有0号进程.
return LOS_OK;
}
......@@ -553,10 +556,10 @@ STATIC UINT32 OsCreateIdleProcess(VOID)
}
//创建一个名叫"KIdle"的进程,并创建一个idle task,CPU空闲的时候就待在 idle task中等待被唤醒
ret = LOS_Fork(CLONE_FILES, "KIdle", (TSK_ENTRY_FUNC)OsIdleTask, LOSCFG_BASE_CORE_TSK_IDLE_STACK_SIZE);
if (ret < 0) {
if (ret < 0) {//内核进程的fork并不会一次调用,返回两次,此子进程执行的开始位置是参数OsIdleTask
return LOS_NOK;
}
g_kernelIdleProcess = (UINT32)ret;//返回进程ID
g_kernelIdleProcess = (UINT32)ret;//返回 0号进程
idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);//通过ID拿到进程实体
*idleTaskID = idleProcess->threadGroupID;//绑定CPU的IdleTask,或者说改变CPU现有的idle任务
......@@ -619,14 +622,14 @@ STATIC LosProcessCB *OsGetFreePCB(VOID)
UINT32 intSave;
SCHEDULER_LOCK(intSave);
if (LOS_ListEmpty(&g_freeProcess)) {//空闲池里还有未分配的task?
if (LOS_ListEmpty(&g_freeProcess)) {//空闲池里还有未分配的进程?
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("No idle PCB in the system!\n");
return NULL;
}
processCB = OS_PCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_freeProcess));//拿到PCB,通过OS_PCB_FROM_PENDLIST是因为通过pendlist 节点挂在 freelist链表上.
LOS_ListDelete(&processCB->pendList);//分配出来了就要在freelist将自己摘除
LOS_ListDelete(&processCB->pendList);//将自己从g_freeProcess链表摘除
SCHEDULER_UNLOCK(intSave);
return processCB;
......@@ -907,7 +910,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsKernelInitProcess(VOID)
processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;// 进程初始化位 置1
g_processGroup = processCB->group;//全局进程组指向了KProcess所在的进程组
LOS_ListInit(&g_processGroup->groupList);// 进程组链表初始化
OsCurrProcessSet(processCB);// 设置为当前进程
OsCurrProcessSet(processCB);// 将KProcess设置为当前进程
return OsCreateIdleProcess();// 创建一个空闲状态的进程
}
......@@ -1547,7 +1550,7 @@ LITE_OS_SEC_TEXT UINT32 OsExecRecycleAndInit(LosProcessCB *processCB, const CHAR
LOS_VmSpaceFree(oldSpace);//ELF已经接管了进程,进程的原有虚拟空间要被释放掉
return LOS_OK;
}
//进程层面的开始执行, entry为入口函数 ,其中 创建好task,task上下文 等待调度真正执行, sp:栈指针 mapBase:栈底 mapSize:栈大小
//执行用户态任务, entry为入口函数 ,其中 创建好task,task上下文 等待调度真正执行, sp:栈指针 mapBase:栈底 mapSize:栈大小
LITE_OS_SEC_TEXT UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINTPTR mapBase, UINT32 mapSize)
{
LosProcessCB *processCB = NULL;
......@@ -1572,12 +1575,13 @@ LITE_OS_SEC_TEXT UINT32 OsExecStart(const TSK_ENTRY_FUNC entry, UINTPTR sp, UINT
taskCB = OsCurrTaskGet();//获取当前任务
processCB->threadGroupID = taskCB->taskID;//threadGroupID是进程的主线程ID,也就是应用程序 main函数线程
taskCB->userMapBase = mapBase;//任务用户态栈底地址
taskCB->userMapSize = mapSize;//任务用户态栈大小
taskCB->userMapBase = mapBase;//用户态栈顶
taskCB->userMapSize = mapSize;//用户态栈大小
taskCB->taskEntry = (TSK_ENTRY_FUNC)entry;//任务的入口函数
taskContext = (TaskContext *)OsTaskStackInit(taskCB->taskID, taskCB->stackSize, (VOID *)taskCB->topOfStack, FALSE);//创建任务上下文
OsUserTaskStackInit(taskContext, taskCB->taskEntry, sp);//用户进程任务栈初始化
taskContext = (TaskContext *)OsTaskStackInit(taskCB->taskID, taskCB->stackSize, (VOID *)taskCB->topOfStack, FALSE);//在内核栈中创建任务上下文
OsUserTaskStackInit(taskContext, taskCB->taskEntry, sp);//初始化用户栈,将内核栈中上下文的 context->R[0] = sp ,context->sp = sp
//这样做的目的是将用户栈SP保存到内核栈中,
SCHEDULER_UNLOCK(intSave);//解锁
return LOS_OK;
}
......@@ -1641,7 +1645,7 @@ LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
(VOID)memset_s((VOID *)((UINTPTR)userText + userInitBssStart - userInitTextStart), initBssSize, 0, initBssSize);// 除了代码段,其余都清0
stack = OsUserInitStackAlloc(g_userInitProcess, &size);//分配任务在用户态下的运行栈,大小为1M,注意此内存来自进程空间,而非内核空间.
stack = OsUserInitStackAlloc(g_userInitProcess, &size);//分配任务在用户态下的运行栈,大小为1M,注意此内存来自用户空间.
if (stack == NULL) {
PRINTK("user init process malloc user stack failed!\n");
ret = LOS_NOK;
......@@ -1696,7 +1700,7 @@ STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name,
childPara->userParam.userArea = mainThread->userArea; //用户态栈区栈顶位置
childPara->userParam.userMapBase = mainThread->userMapBase; //用户态栈底
childPara->userParam.userMapSize = mainThread->userMapSize; //用户态栈大小
} else {
} else {//注意内核态进程创建任务的入口由外界指定,例如 OsCreateIdleProcess 指定了OsIdleTask
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;//参数(sp)为内核态入口地址
childPara->uwStackSize = size;//参数(size)为内核态栈大小
}
......@@ -1987,17 +1991,17 @@ LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status)
OsTaskExitGroup((UINT32)status);
OsProcessExit(OsCurrTaskGet(), (UINT32)status);
}
//获取用户进程的根进程,所有用户进程都是g_processCBArray[g_userInitProcess] fork来的
//获取用户进程的根进程,所有用户进程都是g_processCBArray[g_userInitProcess] fork来的
LITE_OS_SEC_TEXT UINT32 OsGetUserInitProcessID(VOID)
{
return g_userInitProcess;
}
//获取Idel进程,CPU不公正时待的地方,等待被事件唤醒
//获取Idel进程,CPU休息时待的地方,等待被事件唤醒
LITE_OS_SEC_TEXT UINT32 OsGetIdleProcessID(VOID)
{
return g_kernelIdleProcess;
}
//获取内核进程的根进程,所有内核进程都是g_processCBArray[g_kernelInitProcess] fork来的,包括g_processCBArray[g_kernelIdleProcess]进程
//获取内核进程的根进程,所有内核进程都是g_processCBArray[g_kernelInitProcess] fork来的,包括g_processCBArray[g_kernelIdleProcess]进程
LITE_OS_SEC_TEXT UINT32 OsGetKernelInitProcessID(VOID)
{
return g_kernelInitProcess;
......
......@@ -767,7 +767,7 @@ LITE_OS_SEC_TEXT_INIT STATIC VOID OsTaskCBInitBase(LosTaskCB *taskCB,
taskCB->args[1] = initParam->auwArgs[1];
taskCB->args[2] = initParam->auwArgs[2];
taskCB->args[3] = initParam->auwArgs[3];
taskCB->topOfStack = (UINTPTR)topStack; //内核态栈起始位置
taskCB->topOfStack = (UINTPTR)topStack; //内核态栈
taskCB->stackSize = initParam->uwStackSize;//
taskCB->priority = initParam->usTaskPrio;
taskCB->taskEntry = initParam->pfnTaskEntry;
......@@ -805,7 +805,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_IN
LosProcessCB *processCB = NULL;
OsTaskCBInitBase(taskCB, stackPtr, topStack, initParam);//初始化任务的基本信息,
//taskCB->stackPointer = stackPtr ,用户态时将改写taskCB->stackPointer指向
//taskCB->stackPointer指向内核态栈 sp位置,该位置存着 任务初始上下文
SCHEDULER_LOCK(intSave);
processCB = OS_PCB_FROM_PID(initParam->processID);//通过ID获取PCB ,单核进程数最多64个
......@@ -817,7 +817,7 @@ LITE_OS_SEC_TEXT_INIT STATIC UINT32 OsTaskCBInit(LosTaskCB *taskCB, const TSK_IN
taskCB->userMapBase = initParam->userParam.userMapBase;
taskCB->userMapSize = initParam->userParam.userMapSize;
OsUserTaskStackInit(taskCB->stackPointer, taskCB->taskEntry, initParam->userParam.userSP);//初始化用户态任务栈
//这里要注意,任务的上下文是始终保存在内核栈空间,但用户态时运行是在用户态的栈空间.(因为SP指向了用户态空间)
//这里要注意,任务的上下文是始终保存在内核栈空间,而用户态时运行在用户态栈空间.(context->SP = userSP 指向了用户态栈空间)
}
if (!processCB->threadNumber) {//进程线程数量为0时,
......@@ -1584,8 +1584,8 @@ LITE_OS_SEC_TEXT_MINOR UINT32 LOS_TaskInfoGet(UINT32 taskID, TSK_INFO_S *taskInf
taskInfo->usTaskStatus = taskCB->taskStatus;
taskInfo->usTaskPrio = taskCB->priority;
taskInfo->uwStackSize = taskCB->stackSize;
taskInfo->uwTopOfStack = taskCB->topOfStack;
taskInfo->uwStackSize = taskCB->stackSize;//内核态栈大小
taskInfo->uwTopOfStack = taskCB->topOfStack;//内核态栈顶位置
taskInfo->uwEventMask = taskCB->eventMask;
taskInfo->taskEvent = taskCB->taskEvent;
taskInfo->pTaskSem = taskCB->taskSem;
......
......@@ -386,7 +386,7 @@ STATIC INLINE LosProcessCB *OsCurrProcessGet(VOID)
LOS_IntRestore(intSave);//恢复硬件中断
return runProcess;
}
//设置当前进程,加入g_runProcess中
//设置使用CPU的当前进程,加入g_runProcess中
STATIC INLINE VOID OsCurrProcessSet(const LosProcessCB *process)
{
g_runProcess[ArchCurrCpuid()] = (LosProcessCB *)process;
......
......@@ -294,13 +294,13 @@ extern SPIN_LOCK_S g_taskSpin;//任务自旋锁
#define OS_TCB_NAME_LEN 32
typedef struct {
VOID *stackPointer; /**< Task stack pointer */ //栈指针,SP位置,切换任务时先保存上下文并指向TaskContext位置.
VOID *stackPointer; /**< Task stack pointer */ //内核栈指针位置,内核栈默认保存了初始的上下文信息.
UINT16 taskStatus; /**< Task status */ //各种状态标签,可以拥有多种标签,按位标识
UINT16 priority; /**< Task priority */ //任务优先级[0:31],默认是31级
UINT16 policy; //任务的调度方式(三种 .. LOS_SCHED_RR )
UINT16 timeSlice; /**< Remaining time slice *///剩余时间片
UINT32 stackSize; /**< Task stack size */ //栈大小,内存来自内核空间
UINTPTR topOfStack; /**< Task stack top */ //栈顶 bottom = top + size,内存来自内核空间
UINT32 stackSize; /**< Task stack size */ //内核态栈大小,内存来自内核空间
UINTPTR topOfStack; /**< Task stack top */ //内核态栈顶 bottom = top + size
UINT32 taskID; /**< Task ID */ //任务ID,任务池本质是一个大数组,ID就是数组的索引,默认 < 128
TSK_ENTRY_FUNC taskEntry; /**< Task entrance function */ //任务执行入口函数
VOID *joinRetval; /**< pthread adaption */ //用来存储join线程的返回值
......@@ -334,8 +334,8 @@ typedef struct {
SchedStat schedStat; /**< Schedule statistics */ //调度统计
#endif
#endif
UINTPTR userArea; //用户区域,由运行时划定,根据运行态不同而不同
UINTPTR userMapBase; //内存来自进程空间,用户态下的栈底位置,和topOfStack有本质的区别.
UINTPTR userArea; //用户空间,由运行时划定,根据运行态不同而不同
UINTPTR userMapBase; //用户态栈基地址,内存来自用户空间,和topOfStack有本质的区别.
UINT32 userMapSize; /**< user thread stack size ,real size : userMapSize + USER_STACK_MIN_SIZE */
UINT32 processID; /**< Which belong process *///所属进程ID
FutexNode futex; //实现快锁功能
......@@ -395,12 +395,12 @@ STATIC INLINE LosTaskCB *OsCurrTaskGet(VOID)
{
return (LosTaskCB *)ArchCurrTaskGet();
}
//设置当前CPUcore运行任务
//告诉协处理器当前任务使用范围为内核空间
STATIC INLINE VOID OsCurrTaskSet(LosTaskCB *task)
{
ArchCurrTaskSet(task);
}
//用户模式下设置当前Cpucore运行任务,参数为线程
//告诉协处理器当前任务使用范围为 用户空间
STATIC INLINE VOID OsCurrUserTaskSet(UINTPTR thread)
{
ArchCurrUserTaskSet(thread);
......
......@@ -130,10 +130,10 @@ VOID OsSchedResched(VOID)
newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT;//给新任务时间片 默认 20ms
}
OsCurrTaskSet((VOID*)newTask);//设置新的task为CPU核的当前任务
OsCurrTaskSet((VOID*)newTask);//设置新的task为当前任务
if (OsProcessIsUserMode(newProcess)) {//用户模式需自带栈空间
OsCurrUserTaskSet(newTask->userArea);//设置task栈空间
if (OsProcessIsUserMode(newProcess)) {//用户态进程
OsCurrUserTaskSet(newTask->userArea);//向CP15 (c13, 0, c0, 3) 设置当前线程ID
}
PRINT_TRACE("cpu%d run process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x ->\n"
......
......@@ -296,7 +296,7 @@ LITE_OS_SEC_TEXT_INIT INT32 OsMain(VOID)
}
#endif
ret = OsKernelInitProcess();// 完成内核进程的初始化
ret = OsKernelInitProcess();// 初始化内核态根进程
if (ret != LOS_OK) {
return ret;
}
......@@ -387,7 +387,7 @@ STATIC UINT32 OsSystemInitTaskCreate(VOID)
TSK_INIT_PARAM_S sysTask;
(VOID)memset_s(&sysTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
sysTask.pfnTaskEntry = (TSK_ENTRY_FUNC)SystemInit;//任务的入口函数,这个任务由外部提供 比如..\vendor\hi3516dv300\module_init\src\system_init.c
sysTask.pfnTaskEntry = (TSK_ENTRY_FUNC)SystemInit;//任务的入口函数,这个任务由外部提供比如..\vendor\hi3516dv300\module_init\src\system_init.c
sysTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;//16K
sysTask.pcName = "SystemInit";//任务的名称
sysTask.usTaskPrio = LOSCFG_BASE_CORE_TSK_DEFAULT_PRIO;// 内核默认优先级为10
......@@ -423,7 +423,7 @@ UINT32 OsSystemInit(VOID)
#ifdef LOSCFG_COMPAT_LINUXKPI
g_pstSystemWq = create_workqueue("system_wq");
#endif
ret = OsSystemInitTaskCreate();//创建 "SystemInit" 任务
ret = OsSystemInitTaskCreate();//创建 "SystemInit" 任务,用户创建用户态根进程
if (ret != LOS_OK) {
return ret;
}
......
......@@ -92,11 +92,11 @@ typedef struct {
INT32 envc;
CHAR *const *argv;
CHAR *const *envp;
UINTPTR stackTop;
UINTPTR stackTopMax;
UINTPTR stackBase;
UINTPTR stackTop; //当前栈顶
UINTPTR stackTopMax; //栈顶最大值,其实必 stackTopMax < stackTop
UINTPTR stackBase; //栈底
UINTPTR stackParamBase;
UINT32 stackSize;
UINT32 stackSize;//栈大小
INT32 stackProt;
UINTPTR loadAddr;
UINTPTR elfEntry; //入口函数位置
......
......@@ -94,7 +94,7 @@ void SyscallHandleInit(void)
/* The SYSCALL ID is in R7 on entry. Parameters follow in R0..R6 */
/******************************************************************
由汇编调用,见于 los_hw_exc.s 第197行 BLX OsArmA32SyscallHandle
由汇编调用,见于 los_hw_exc.s / BLX OsArmA32SyscallHandle
SYSCALL是产生系统调用时触发的信号,R7寄存器存放具体的系统调用ID,也叫系统调用号
regs:参数就是所有寄存器
注意:本函数在用户态和内核态下都可能被调用到
......@@ -112,8 +112,8 @@ LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)
return regs;
}
if (cmd == __NR_sigreturn) {//此时运行在内核栈,程序返回的调用,从内核态返回用户态时触发
OsRestorSignalContext(regs);//恢复信号上下文,执行完函数后,切到了用户栈
if (cmd == __NR_sigreturn) {//收到 __NR_sigreturn 信号
OsRestorSignalContext(regs);//恢复信号上下文
return regs;
}
......@@ -131,7 +131,7 @@ LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)
case ARG_NUM_1:
ret = (*(SyscallFun1)handle)(regs[REG_R0]);//执行系统调用,类似 SysUnlink(pathname);
break;
case ARG_NUM_2://@note_thinking 如何是两个参数的系统调用,这里传的确是三个参数,任务栈中会出现怎样的情况呢?
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;
......@@ -146,7 +146,7 @@ LITE_OS_SEC_TEXT UINT32 *OsArmA32SyscallHandle(UINT32 *regs)
}
regs[REG_R0] = ret;//R0保存系统调用返回值
OsSaveSignalContext(regs);//保存用户栈现场
OsSaveSignalContext(regs);//保存信号上下文现场
/* Return the last value of curent_regs. This supports context switches on return from the exception.
* That capability is only used with theSYS_context_switch system call.
......
git add -A
git commit -m '用户态,内核态代码注解
git commit -m '注解0号进程是如何创建的?
百万汉字注解 + 百篇博客分析 => 挖透鸿蒙内核源码
https://my.oschina.net/weharmony
'
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册