From 3231b208fa6b5fc752933e8662b19085e7d0c9ec Mon Sep 17 00:00:00 2001 From: kuangyufei Date: Fri, 23 Oct 2020 11:54:55 +0800 Subject: [PATCH] =?UTF-8?q?=E9=B8=BF=E8=92=99=E6=BA=90=E7=A0=81=E5=88=86?= =?UTF-8?q?=E6=9E=90=E7=B3=BB=E5=88=97=E7=AF=87=20https://blog.csdn.net/ku?= =?UTF-8?q?angyufei=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20http?= =?UTF-8?q?s://my.oschina.net/u/3751245?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 6 ++-- kernel/base/core/los_process.c | 42 ++++++++++++------------ kernel/base/core/los_task.c | 44 ++++++++++++------------- kernel/base/sched/sched_sq/los_sched.c | 44 ++++++++++++------------- kernel/include/los_task.h | 2 +- zzz/test/mux.c | 45 -------------------------- 6 files changed, 69 insertions(+), 114 deletions(-) delete mode 100644 zzz/test/mux.c diff --git a/README.md b/README.md index daea22a7..cd8a3981 100644 --- a/README.md +++ b/README.md @@ -11,15 +11,15 @@ * ### **致敬鸿蒙内核开发者** - 感谢开放原子开源基金会,鸿蒙内核开发者提供了如此优秀的源码,让笔者一了多年的夙愿,津津乐道与此.越深入精读内核源码,越能感受到设计者的精巧用心,创新突破. 向开发者致敬ppp. 可以毫不夸张的说 kernel_liteos_a 可作为大学C语言,数据结构,操作系统,汇编语言 四门课程的教学项目.如此宝库,不深入研究真会觉得太可惜了. + 感谢开放原子开源基金会,鸿蒙内核开发者提供了如此优秀的源码,让笔者一了多年的夙愿,津津乐道于此.越深入精读内核源码,越能感受到设计者的精巧用心,创新突破. 向开发者致敬ppp. 可以毫不夸张的说 kernel_liteos_a 可作为大学C语言,数据结构,操作系统,汇编语言 四门课程的教学项目.如此宝库,不深入研究实在是太可惜了. * ### **系列篇和源码注释怎么更新** 好记性不如烂笔头,笔者把研究过程心得写成鸿蒙源码分析系列篇,如此源码注释结合系列篇文章理解鸿蒙内核实现会更彻底. - 系列篇文章查看: 进入>> 鸿蒙源码分析系列篇 [CSDN站](https://blog.csdn.net/kuangyufei) | [oschina站](https://my.oschina.net/u/3751245) 查看, 正在持续更新中..., 感谢CSDN, oschina 对博文的推荐. + 系列篇文章查看: 进入>> 鸿蒙源码分析系列篇 [CSDN站](https://blog.csdn.net/kuangyufei) | [OSCHINA站](https://my.oschina.net/u/3751245) 查看, 正在持续更新中..., 感谢CSDN, OSCHINA 对博文的推荐. - 注释中文版查看: 进入>> 鸿蒙内核源码注释中文版 [CSDN仓库](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [Gitee仓库 ](https://gitee.com/weharmony/kernel_liteos_a_note) | [Github仓库](https://github.com/kuangyufei/kernel_liteos_a_note) 查看,三大仓库同步更新. 正在持续加注中.... + 注释中文版查看: 进入>> 鸿蒙内核源码注释中文版 [CSDN仓库](https://codechina.csdn.net/kuangyufei/kernel_liteos_a_note) | [Gitee仓库 ](https://gitee.com/weharmony/kernel_liteos_a_note) | [Github仓库](https://github.com/kuangyufei/kernel_liteos_a_note) [coding仓库](https://weharmony.coding.net/public/harmony/kernel_liteos_a_note/git/files) 查看,四大仓库同步更新. 正在持续加注中.... 精读内核源码当然是件很困难的事,但正因为很难才值得去做! 内心不渴望的永远不可能靠近自己.别再去纠结而没有行动.笔者一直坚信兴趣是最好的老师,加注就是在做自己感兴趣的事, 希望感兴趣的各位能看到.如果能让更多人参与到内核的研究,减少学习的成本,哪怕就节省一天的时间,这么多人能节省多少时间, 这是件多好玩,多有意义的事情啊. diff --git a/kernel/base/core/los_process.c b/kernel/base/core/los_process.c index 790ff166..7ac932ff 100644 --- a/kernel/base/core/los_process.c +++ b/kernel/base/core/los_process.c @@ -498,66 +498,66 @@ STATIC VOID OsProcessNaturalExit(LosTaskCB *runTask, UINT32 status) LOS_Panic("pid : %u is the root process exit!\n", processCB->processID); return; } - -LITE_OS_SEC_TEXT_INIT UINT32 OsProcessInit(VOID)//进程模块初始化 +//进程模块初始化,被编译放在代码段 .init 中 +LITE_OS_SEC_TEXT_INIT UINT32 OsProcessInit(VOID) { UINT32 index; UINT32 size; - g_processMaxNum = LOSCFG_BASE_CORE_PROCESS_LIMIT;// 默认是64个 - size = g_processMaxNum * sizeof(LosProcessCB); + g_processMaxNum = LOSCFG_BASE_CORE_PROCESS_LIMIT;//默认支持64个进程 + size = g_processMaxNum * sizeof(LosProcessCB);//算出总大小 - g_processCBArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);// 进程池,占用内核堆 + g_processCBArray = (LosProcessCB *)LOS_MemAlloc(m_aucSysMem1, size);// 进程池,占用内核堆,内存池分配 if (g_processCBArray == NULL) { return LOS_NOK; } - (VOID)memset_s(g_processCBArray, size, 0, size);//安全方式重置 + (VOID)memset_s(g_processCBArray, size, 0, size);//安全方式重置清0 LOS_ListInit(&g_freeProcess);//进程空闲链表初始化,创建一个进程时从g_freeProcess中申请一个进程描述符使用 LOS_ListInit(&g_processRecyleList);//进程回收链表初始化,回收完成后进入g_freeProcess等待再次被申请使用 - for (index = 0; index < g_processMaxNum; index++) { + for (index = 0; index < g_processMaxNum; index++) {//进程池循环创建 g_processCBArray[index].processID = index;//进程ID[0-g_processMaxNum]赋值 g_processCBArray[index].processStatus = OS_PROCESS_FLAG_UNUSED;// 默认都是白纸一张,臣妾干净着呢 LOS_ListTailInsert(&g_freeProcess, &g_processCBArray[index].pendList);// 初始全是可分配进程描述符 } - - g_userInitProcess = 1; /* 1: The root process ID of the user-mode process is fixed at 1 */ + // ????? 为啥用户模式的根进程 选1 ,内核模式的根进程选2 + 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链表 - g_kernelInitProcess = 2; /* 2: The root process ID of the kernel-mode process is fixed at 2 */ + 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链表 return LOS_OK; } - +//创建一个名叫"KIdle"的进程,给CPU空闲的时候使用 STATIC UINT32 OsCreateIdleProcess(VOID) { UINT32 ret; CHAR *idleName = "Idle"; LosProcessCB *idleProcess = NULL; Percpu *perCpu = OsPercpuGet(); - UINT32 *idleTaskID = &perCpu->idleTaskID; + UINT32 *idleTaskID = &perCpu->idleTaskID;//得到CPU的idle task - ret = OsCreateResourceFreeTask();// 创建一个资源回收任务 + ret = OsCreateResourceFreeTask();// 创建一个资源回收任务,优先级为5 用于回收进程退出时的各种资源 if (ret != LOS_OK) { return ret; } - + //创建一个名叫"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) { return LOS_NOK; } - g_kernelIdleProcess = (UINT32)ret; + g_kernelIdleProcess = (UINT32)ret;//返回进程ID - idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess); - *idleTaskID = idleProcess->threadGroupID; - OS_TCB_FROM_TID(*idleTaskID)->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK; + idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);//通过ID拿到进程实体 + *idleTaskID = idleProcess->threadGroupID;//绑定CPU的IdleTask,或者说改变CPU现有的idle任务 + OS_TCB_FROM_TID(*idleTaskID)->taskStatus |= OS_TASK_FLAG_SYSTEM_TASK;//设定Idle task 为一个系统任务 #if (LOSCFG_KERNEL_SMP == YES) - OS_TCB_FROM_TID(*idleTaskID)->cpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid()); + OS_TCB_FROM_TID(*idleTaskID)->cpuAffiMask = CPUID_TO_AFFI_MASK(ArchCurrCpuid());//多核CPU的任务指定,防止乱串了,注意多核才会有并行处理 #endif - (VOID)memset_s(OS_TCB_FROM_TID(*idleTaskID)->taskName, OS_TCB_NAME_LEN, 0, OS_TCB_NAME_LEN); - (VOID)memcpy_s(OS_TCB_FROM_TID(*idleTaskID)->taskName, OS_TCB_NAME_LEN, idleName, strlen(idleName)); + (VOID)memset_s(OS_TCB_FROM_TID(*idleTaskID)->taskName, OS_TCB_NAME_LEN, 0, OS_TCB_NAME_LEN);//task 名字先清0 + (VOID)memcpy_s(OS_TCB_FROM_TID(*idleTaskID)->taskName, OS_TCB_NAME_LEN, idleName, strlen(idleName));//task 名字叫 idle return LOS_OK; } diff --git a/kernel/base/core/los_task.c b/kernel/base/core/los_task.c index deb5ab65..b287e9b1 100644 --- a/kernel/base/core/los_task.c +++ b/kernel/base/core/los_task.c @@ -124,10 +124,10 @@ VOID OsSetMainTask() LOS_ListInit(&g_mainTask[i].lockList);//初始化 每个CPU core 持有的锁链表 } } - -LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID)//空任务 +//空闲任务 注意 #define WEAK __attribute__((weak)) 是用于防止crash的 +LITE_OS_SEC_TEXT WEAK VOID OsIdleTask(VOID) { - while (1) { + while (1) {//只有一个死循环 #ifdef LOSCFG_KERNEL_TICKLESS if (OsTickIrqFlagGet()) { OsTickIrqFlagSet(0); @@ -243,7 +243,7 @@ LITE_OS_SEC_TEXT UINT32 OsTaskSetDeatchUnsafe(LosTaskCB *taskCB) return LOS_EINVAL; } - +//任务扫描 LITE_OS_SEC_TEXT VOID OsTaskScan(VOID) { SortLinkList *sortList = NULL; @@ -253,7 +253,7 @@ LITE_OS_SEC_TEXT VOID OsTaskScan(VOID) LOS_DL_LIST *listObject = NULL; SortLinkAttribute *taskSortLink = NULL; - taskSortLink = &OsPercpuGet()->taskSortLink; + taskSortLink = &OsPercpuGet()->taskSortLink;//获取任务的排序链表 taskSortLink->cursor = (taskSortLink->cursor + 1) & OS_TSK_SORTLINK_MASK; listObject = taskSortLink->sortLink + taskSortLink->cursor; @@ -841,7 +841,7 @@ LOS_ERREND_REWIND_TCB: LOS_ERREND: return errRet; } - +//创建Task LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *initParam) { UINT32 ret; @@ -856,35 +856,35 @@ LITE_OS_SEC_TEXT_INIT UINT32 LOS_TaskCreate(UINT32 *taskID, TSK_INIT_PARAM_S *in return LOS_ERRNO_TSK_YIELD_IN_INT; } - if (initParam->uwResved & OS_TASK_FLAG_IDLEFLAG) { - initParam->processID = OsGetIdleProcessID(); - } else if (OsProcessIsUserMode(OsCurrProcessGet())) { - initParam->processID = OsGetKernelInitProcessID(); + if (initParam->uwResved & OS_TASK_FLAG_IDLEFLAG) {//OS_TASK_FLAG_IDLEFLAG 是属于内核 idle进程专用的 + initParam->processID = OsGetIdleProcessID();//获取空闲进程 + } else if (OsProcessIsUserMode(OsCurrProcessGet())) {//当前进程是否为用户模式 + initParam->processID = OsGetKernelInitProcessID();//不是就取"Kernel"进程 } else { - initParam->processID = OsCurrProcessGet()->processID; + initParam->processID = OsCurrProcessGet()->processID;//获取当前进程 ID赋值 } - initParam->uwResved &= ~OS_TASK_FLAG_IDLEFLAG; - initParam->uwResved &= ~OS_TASK_FLAG_PTHREAD_JOIN; - if (initParam->uwResved & LOS_TASK_STATUS_DETACHED) { - initParam->uwResved = OS_TASK_FLAG_DETACHED; + initParam->uwResved &= ~OS_TASK_FLAG_IDLEFLAG;//不能是 OS_TASK_FLAG_IDLEFLAG + initParam->uwResved &= ~OS_TASK_FLAG_PTHREAD_JOIN;//不能是 OS_TASK_FLAG_PTHREAD_JOIN + if (initParam->uwResved & LOS_TASK_STATUS_DETACHED) {//是否设置了自动删除 + initParam->uwResved = OS_TASK_FLAG_DETACHED;//自动删除,注意这里是 = ,也就是说只有 OS_TASK_FLAG_DETACHED 一个标签了 } - ret = LOS_TaskCreateOnly(taskID, initParam); + ret = LOS_TaskCreateOnly(taskID, initParam);//创建一个任务,这是任务创建的实体,前面都只是前期准备工作 if (ret != LOS_OK) { return ret; } - taskCB = OS_TCB_FROM_TID(*taskID); + taskCB = OS_TCB_FROM_TID(*taskID);//通过ID拿到task实体 SCHEDULER_LOCK(intSave); - taskCB->taskStatus &= ~OS_TASK_STATUS_INIT; - OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, 0); + taskCB->taskStatus &= ~OS_TASK_STATUS_INIT;//任务不再是初始化 + OS_TASK_SCHED_QUEUE_ENQUEUE(taskCB, 0);//进入调度就绪队列,新任务是直接进入就绪队列的 SCHEDULER_UNLOCK(intSave); /* in case created task not running on this core, schedule or not depends on other schedulers status. */ - LOS_MpSchedule(OS_MP_CPU_ALL); - if (OS_SCHEDULER_ACTIVE) { - LOS_Schedule(); + LOS_MpSchedule(OS_MP_CPU_ALL);//如果创建的任务没有在这个核心上运行,是否调度取决于其他调度程序的状态。 + if (OS_SCHEDULER_ACTIVE) {//当前CPU核处于可调度状态 + LOS_Schedule();//发起调度 } return LOS_OK; diff --git a/kernel/base/sched/sched_sq/los_sched.c b/kernel/base/sched/sched_sq/los_sched.c index a9e11764..1c0bedde 100644 --- a/kernel/base/sched/sched_sq/los_sched.c +++ b/kernel/base/sched/sched_sq/los_sched.c @@ -82,7 +82,7 @@ STATIC VOID OsSchedSwitchProcess(LosProcessCB *runProcess, LosProcessCB *newProc newProcess->timeSlice = OS_PROCESS_SCHED_RR_INTERVAL;//重新分配时间片,默认 20ms } } - +//重新调度实现 VOID OsSchedResched(VOID) { LosTaskCB *runTask = NULL; @@ -90,50 +90,50 @@ VOID OsSchedResched(VOID) LosProcessCB *runProcess = NULL; LosProcessCB *newProcess = NULL; - LOS_ASSERT(LOS_SpinHeld(&g_taskSpin)); + LOS_ASSERT(LOS_SpinHeld(&g_taskSpin));//必须持有任务自旋锁,自旋锁是不是进程层面去抢锁,而是CPU各自核之间去争夺锁 - if (!OsPreemptableInSched()) { + if (!OsPreemptableInSched()) {//是否置了重新调度标识位 return; } - runTask = OsCurrTaskGet(); - newTask = OsGetTopTask(); + runTask = OsCurrTaskGet();//获取当前任务 + newTask = OsGetTopTask();//获取优先级最最最高的任务 /* always be able to get one task */ - LOS_ASSERT(newTask != NULL); + LOS_ASSERT(newTask != NULL);//不能没有需调度的任务 - if (runTask == newTask) { + if (runTask == newTask) {//当前任务就是最高任务,那还调度个啥的,直接退出. return; } - runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING; - newTask->taskStatus |= OS_TASK_STATUS_RUNNING; + runTask->taskStatus &= ~OS_TASK_STATUS_RUNNING;//当前任务状态位置成不在运行状态 + newTask->taskStatus |= OS_TASK_STATUS_RUNNING;//最高任务状态位置成在运行状态 - runProcess = OS_PCB_FROM_PID(runTask->processID); - newProcess = OS_PCB_FROM_PID(newTask->processID); + runProcess = OS_PCB_FROM_PID(runTask->processID);//通过进程ID索引拿到进程实体 + newProcess = OS_PCB_FROM_PID(newTask->processID);//同上 - OsSchedSwitchProcess(runProcess, newProcess); + OsSchedSwitchProcess(runProcess, newProcess);//切换进程,里面主要涉及进程空间的切换,也就是MMU的上下文切换. -#if (LOSCFG_KERNEL_SMP == YES) +#if (LOSCFG_KERNEL_SMP == YES)//CPU多核的情况 /* mask new running task's owner processor */ - runTask->currCpu = OS_TASK_INVALID_CPUID; - newTask->currCpu = ArchCurrCpuid(); + runTask->currCpu = OS_TASK_INVALID_CPUID;//当前任务不占用CPU + newTask->currCpu = ArchCurrCpuid();//让新任务占用CPU #endif - (VOID)OsTaskSwitchCheck(runTask, newTask); + (VOID)OsTaskSwitchCheck(runTask, newTask);//切换task的检查 #if (LOSCFG_KERNEL_SCHED_STATISTICS == YES) OsSchedStatistics(runTask, newTask); #endif - if ((newTask->timeSlice == 0) && (newTask->policy == LOS_SCHED_RR)) { - newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT; + if ((newTask->timeSlice == 0) && (newTask->policy == LOS_SCHED_RR)) {//没有时间片且是抢占式调度的方式,注意 非抢占式都不需要时间片的. + newTask->timeSlice = LOSCFG_BASE_CORE_TIMESLICE_TIMEOUT;//给新任务时间片 默认 20ms } - OsCurrTaskSet((VOID*)newTask); + OsCurrTaskSet((VOID*)newTask);//设置新的task为CPU核的当前任务 - if (OsProcessIsUserMode(newProcess)) { - OsCurrUserTaskSet(newTask->userArea); + if (OsProcessIsUserMode(newProcess)) {//用户模式下会怎么样? + OsCurrUserTaskSet(newTask->userArea);//设置task栈空间 } PRINT_TRACE("cpu%d run process name: (%s) pid: %d status: %x threadMap: %x task name: (%s) tid: %d status: %x ->\n" @@ -145,7 +145,7 @@ VOID OsSchedResched(VOID) newProcess->threadScheduleMap, newTask->taskName, newTask->taskID, newTask->taskStatus); /* do the task context switch */ - OsTaskSchedule(newTask, runTask); + OsTaskSchedule(newTask, runTask);//再执行调度,主要是切换CPU的上下文 } VOID OsSchedPreempt(VOID) diff --git a/kernel/include/los_task.h b/kernel/include/los_task.h index afae40ca..2f46f7c8 100644 --- a/kernel/include/los_task.h +++ b/kernel/include/los_task.h @@ -491,7 +491,7 @@ typedef struct { * * Information of specified parameters passed in during task creation. */ -typedef struct tagTskInitParam { +typedef struct tagTskInitParam {//Task的初始化参数 TSK_ENTRY_FUNC pfnTaskEntry; /**< Task entrance function */ UINT16 usTaskPrio; /**< Task priority */ UINT16 policy; /**< Task policy */ diff --git a/zzz/test/mux.c b/zzz/test/mux.c deleted file mode 100644 index 7349d024..00000000 --- a/zzz/test/mux.c +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include -#include - -// 打印机 -void printer(char *str) -{ - while(*str!='\0') - { - putchar(*str); - fflush(stdout); - str++; - sleep(1); - } - printf("\n"); -} - -// 线程一 -void *thread_fun_1(void *arg) -{ - char *str = "hello"; - printer(str); //打印 -} - -// 线程二 -void *thread_fun_2(void *arg) -{ - char *str = "world"; - printer(str); //打印 -} - -int main(void) -{ - pthread_t tid1, tid2; - - // 创建 2 个线程 - pthread_create(&tid1, NULL, thread_fun_1, NULL); - pthread_create(&tid2, NULL, thread_fun_2, NULL); - - // 等待线程结束,回收其资源 - pthread_join(tid1, NULL); - pthread_join(tid2, NULL); - - return 0; -} \ No newline at end of file -- GitLab