```c // 去掉初始化标签 kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT; g_processGroup = kerInitProcess->group; LOS_ListInit(&g_processGroup->groupList); OsCurrProcessSet(kerInitProcess); // 创建内核态0号进程 LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess); ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, OS_TASK_PRIORITY_LOWEST, "KIdle"); if (ret != LOS_OK) { return ret; } idleProcess->parentProcessID = kerInitProcess->processID; LOS_ListTailInsert(&kerInitProcess->childrenList, &idleProcess->siblingList); idleProcess->group = kerInitProcess->group; LOS_ListTailInsert(&kerInitProcess->group->processList, &idleProcess->subordinateGroupList); #ifdef LOSCFG_SECURITY_CAPABILITY idleProcess->user = kerInitProcess->user; #endif #ifdef LOSCFG_FS_VFS idleProcess->files = kerInitProcess->files; #endif // 创建空闲任务并将其指定给内核态0号进程 ret = OsIdleTaskCreate(); if (ret != LOS_OK) { return ret; } idleProcess->threadGroupID = OsPercpuGet()->idleTaskID; return LOS_OK; ``` ```c // 进程调度参数检查 STATIC INLINE INT32 OsProcessSchedlerParamCheck(INT32 which, INT32 pid, UINT16 prio, UINT16 policy) { if (OS_PID_CHECK_INVALID(pid)) { return LOS_EINVAL; } if (which != LOS_PRIO_PROCESS) { return LOS_EINVAL; } if (prio > OS_PROCESS_PRIORITY_LOWEST) { return LOS_EINVAL; } if (policy != LOS_SCHED_RR) { return LOS_EINVAL; } return LOS_OK; } #ifdef LOSCFG_SECURITY_CAPABILITY STATIC BOOL OsProcessCapPermitCheck(const LosProcessCB *processCB, UINT16 prio) { LosProcessCB *runProcess = OsCurrProcessGet(); // 对于内核态进程直接通过检查 if (!OsProcessIsUserMode(runProcess)) { return TRUE; } // 用户态进程可以降低自己的优先级 if ((runProcess->processID == processCB->processID) && (prio > processCB->priority)) { return TRUE; } // 如果具有 CAP_SCHED_SETPRIORITY 权限,可以修改进程的优先级 if (IsCapPermit(CAP_SCHED_SETPRIORITY)) { return TRUE; } return FALSE; } #endif LITE_OS_SEC_TEXT INT32 OsSetProcessScheduler(INT32 which, INT32 pid, UINT16 prio, UINT16 policy) { LosProcessCB *processCB = NULL; BOOL needSched = FALSE; UINT32 intSave; INT32 ret; ret = OsProcessSchedlerParamCheck(which, pid, prio, policy); if (ret != LOS_OK) { return -ret; } SCHEDULER_LOCK(intSave); processCB = OS_PCB_FROM_PID(pid); // 如果进程未激活,则返回错误 if (OsProcessIsInactive(processCB)) { ret = LOS_ESRCH; goto EXIT; } #ifdef LOSCFG_SECURITY_CAPABILITY // 如果权限不足,则返回错误 if (!OsProcessCapPermitCheck(processCB, prio)) { ret = LOS_EPERM; goto EXIT; } #endif // 修改进程调度参数,判断是否需要进行调度 needSched = OsSchedModifyProcessSchedParam(processCB, policy, prio); SCHEDULER_UNLOCK(intSave); // 调度其他核上的进程 LOS_MpSchedule(OS_MP_CPU_ALL); // 如果需要调度且调度器已经激活,则进行调度 if (needSched && OS_SCHEDULER_ACTIVE) { LOS_Schedule(); } return LOS_OK; EXIT: SCHEDULER_UNLOCK(intSave); return -ret; } LITE_OS_SEC_TEXT INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio) { return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, policy); } LITE_OS_SEC_TEXT INT32 LOS_GetProcessScheduler(INT32 pid) { UINT32 intSave; if (OS_PID_CHECK_INVALID(pid)) { return -LOS_EINVAL; } SCHEDULER_LOCK(intSave); LosProcessCB *processCB = OS_PCB_FROM_PID(pid); // 如果进程未使用,则返回错误 if (OsProcessIsUnused(processCB)) { SCHEDULER_UNLOCK(intSave); return -LOS_ESRCH; } SCHEDULER_UNLOCK(intSave); return LOS_SCHED_RR; } LITE_OS_SEC_TEXT INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio) { return OsSetProcessScheduler(LOS_PRIO_PROCESS, pid, prio, LOS_GetProcessScheduler(pid)); } LITE_OS_SEC_TEXT INT32 OsGetProcessPriority(INT32 which, INT32 pid) { LosProcessCB *processCB = NULL; INT32 prio; UINT32 intSave; (VOID)which; if (OS_PID_CHECK_INVALID(pid)) { return -LOS_EINVAL; } if (which != LOS_PRIO_PROCESS) { return -LOS_EINVAL; } SCHEDULER_LOCK(intSave); processCB = OS_PCB_FROM_PID(pid); // 如果进程未使用,则返回错误 if (OsProcessIsUnused(processCB)) { prio = -LOS_ESRCH; goto OUT; } prio = (INT32)processCB->priority; OUT: SCHEDULER_UNLOCK(intSave); return prio; } LITE_OS_SEC_TEXT INT32 LOS_GetProcessPriority(INT32 pid) { return OsGetProcessPriority(LOS_PRIO_PROCESS, pid); } // 将运行任务插入等待列表 STATIC VOID OsWaitInsertWaitListInOrder(LosTaskCB *runTask, LosProcessCB *processCB) { LOS_DL_LIST *head = &processCB->waitList; LOS_DL_LIST *list = head; LosTaskCB *taskCB = NULL; if (runTask->waitFlag == OS_PROCESS_WAIT_GID) { while (list->pstNext != head) { taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list)); // 如果等待标记为 OS_PROCESS_WAIT_PRO,则继续查找下一个等待队列 if (taskCB->waitFlag == OS_PROCESS_WAIT_PRO) { list = list->pstNext; continue; } break; } } else if (runTask->waitFlag == OS_PROCESS_WAIT_ANY) { while (list->pstNext != head) { taskCB = OS_TCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(list)); // 如果等待标记不为 OS_PROCESS_WAIT_ANY,则继续查找下一个等待队列 if (taskCB->waitFlag != OS_PROCESS_WAIT_ANY) { list = list->pstNext; continue; } break; } } } ``` // 等待指定的子进程退出 STATIC UINT32 OsWaitSetFlag(const LosProcessCB *processCB, INT32 pid, LosProcessCB **child) { LosProcessCB *childCB = NULL; ProcessGroup *group = NULL; LosTaskCB *runTask = OsCurrTaskGet(); // 获取当前运行的任务控制块 UINT32 ret; if (pid > 0) { // 等待具有指定进程号的子进程退出 childCB = OsFindExitChildProcess(processCB, pid); // 查找具有指定进程号的已退出的子进程 if (childCB != NULL) { goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 } ret = OsFindChildProcess(processCB, pid); // 查找具有指定进程号的子进程是否存在 if (ret != LOS_OK) { return LOS_ECHILD; // 没有找到指定进程号的子进程,返回错误码LOS_ECHILD } runTask->waitFlag = OS_PROCESS_WAIT_PRO; // 设置当前任务的等待标志为进程号 runTask->waitID = pid; // 设置当前任务等待的进程号为指定进程号 } else if (pid == 0) { // 等待同一进程组中的任何子进程退出 childCB = OsFindGroupExitProcess(processCB->group, OS_INVALID_VALUE); // 查找同一进程组中的已退出的子进程 if (childCB != NULL) { goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 } runTask->waitID = processCB->group->groupID; // 设置当前任务等待的进程号为进程组号 runTask->waitFlag = OS_PROCESS_WAIT_GID; // 设置当前任务的等待标志为进程组号 } else if (pid == -1) { // 等待任何子进程退出 childCB = OsFindExitChildProcess(processCB, OS_INVALID_VALUE); // 查找任何已退出的子进程 if (childCB != NULL) { goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 } runTask->waitID = pid; // 设置当前任务等待的进程号为-1 runTask->waitFlag = OS_PROCESS_WAIT_ANY; // 设置当前任务的等待标志为任何子进程 } else { // pid < -1 // 等待进程组号为pid绝对值的任何子进程退出 group = OsFindProcessGroup(-pid); // 查找具有指定进程组号的进程组 if (group == NULL) { return LOS_ECHILD; // 没有找到指定进程组号的进程组,返回错误码LOS_ECHILD } childCB = OsFindGroupExitProcess(group, OS_INVALID_VALUE); // 查找指定进程组中已退出的子进程 if (childCB != NULL) { goto WAIT_BACK; // 子进程已退出,则跳转到WAIT_BACK标签处 } runTask->waitID = -pid; // 设置当前任务等待的进程号为进程组号的绝对值 runTask->waitFlag = OS_PROCESS_WAIT_GID; // 设置当前任务的等待标志为进程组号 } WAIT_BACK: *child = childCB; // 返回已退出的子进程 return LOS_OK; } // 回收已退出的子进程资源,并返回进程号 STATIC UINT32 OsWaitRecycleChildProcess(const LosProcessCB *childCB, UINT32 intSave, INT32 *status, siginfo_t *info) { ProcessGroup *group = NULL; UINT32 pid = childCB->processID; // 子进程的进程号 UINT16 mode = childCB->processMode; // 子进程的运行模式 INT32 exitCode = childCB->exitCode; // 子进程的退出码 UINT32 uid = 0; #ifdef LOSCFG_SECURITY_CAPABILITY if (childCB->user != NULL) { uid = childCB->user->userID; // 子进程的用户ID } #endif OsRecycleZombiesProcess((LosProcessCB *)childCB, &group); // 回收已退出的子进程资源,并获取进程组 SCHEDULER_UNLOCK(intSave); // 解锁调度器 if (status != NULL) { if (mode == OS_USER_MODE) { (VOID)LOS_ArchCopyToUser((VOID *)status, (const VOID *)(&(exitCode)), sizeof(INT32)); // 拷贝退出码到用户空间 } else { *status = exitCode; // 将退出码保存到status中 } } /* get signal info */ if (info != NULL) { siginfo_t tempinfo = { 0 }; tempinfo.si_signo = SIGCHLD; tempinfo.si_errno = 0; tempinfo.si_pid = pid; tempinfo.si_uid = uid; /* * Process exit code * 31 15 8 7 0 * | | exit code | core dump | signal | */ if ((exitCode & 0x7f) == 0) { tempinfo.si_code = CLD_EXITED; tempinfo.si_status = (exitCode >> 8U); } else { tempinfo.si_code = (exitCode & 0x80) ? CLD_DUMPED : CLD_KILLED; tempinfo.si_status = (exitCode & 0x7f); } if (mode == OS_USER_MODE) { (VOID)LOS_ArchCopyToUser((VOID *)(info), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); // 拷贝信号信息到用户空间 } else { (VOID)memcpy_s((VOID *)(info), sizeof(siginfo_t), (const VOID *)(&(tempinfo)), sizeof(siginfo_t)); } } (VOID)LOS_MemFree(m_aucSysMem1, group); // 释放进程组资源 return pid; // 返回子进程的进程号 } // 检查等待子进程的具体信息 STATIC UINT32 OsWaitChildProcessCheck(LosProcessCB *processCB, INT32 pid, LosProcessCB **childCB) { if (LOS_ListEmpty(&(processCB->childrenList)) && LOS_ListEmpty(&(processCB->exitChildList))) { return LOS_ECHILD; // 没有子进程,则返回错误码LOS_ECHILD } return OsWaitSetFlag(processCB, pid, childCB); // 设置等待标志等信息 } // 检查等待选项是否正确 STATIC UINT32 OsWaitOptionsCheck(UINT32 options) { UINT32 flag = LOS_WAIT_WNOHANG | LOS_WAIT_WUNTRACED | LOS_WAIT_WCONTINUED; flag = ~flag & options; if (flag != 0) { return LOS_EINVAL; // 选项不正确,返回错误码LOS_EINVAL } if ((options & (LOS_WAIT_WCONTINUED | LOS_WAIT_WUNTRACED)) != 0) { return LOS_EOPNOTSUPP; // 不支持的选项,返回错误码LOS_EOPNOTSUPP } if (OS_INT_ACTIVE) { return LOS_EINTR; // 当前处于中断上下文中,返回错误码LOS_EINTR } return LOS_OK; // 选项正确,返回LOS_OK } // 等待子进程退出 STATIC INT32 OsWait(INT32 pid, USER INT32 *status, USER siginfo_t *info, UINT32 options, VOID *rusage) { (VOID)rusage; UINT32 ret; UINT32 intSave; LosProcessCB *childCB = NULL; LosProcessCB *processCB = NULL; LosTaskCB *runTask = NULL; SCHEDULER_LOCK(intSave); // 加锁调度器 processCB = OsCurrProcessGet(); // 获取当前进程控制块 runTask = OsCurrTaskGet(); // 获取当前任务控制块 ret = OsWaitChildProcessCheck(processCB, pid, &childCB); // 检查等待子进程的具体信息 if (ret != LOS_OK) { pid = -ret; // 若等待子进程的标志不正确,将错误码赋值给pid goto ERROR; } if (childCB != NULL) { return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); // 回收已退出的子进程资源并返回进程号 } if ((options & LOS_WAIT_WNOHANG) != 0) { runTask->waitFlag = 0; // 不阻塞任务 pid = 0; goto ERROR; } OsWaitInsertWaitListInOrder(runTask, processCB); // 将当前任务插入等待列表中 runTask->waitFlag = 0; if (runTask->waitID == OS_INVALID_VALUE) { pid = -LOS_ECHILD; // 没有子进程需要等待,返回错误码LOS_ECHILD goto ERROR; } childCB = OS_PCB_FROM_PID(runTask->waitID); // 根据等待的进程号获取子进程控制块 if (!(childCB->processStatus & OS_PROCESS_STATUS_ZOMBIES)) { pid = -LOS_ESRCH; // 子进程没有退出,返回错误码LOS_ESRCH goto ERROR; } return (INT32)OsWaitRecycleChildProcess(childCB, intSave, status, info); // 回收已退出的子进程资源并返回进程号 ERROR: SCHEDULER_UNLOCK(intSave); // 解锁调度器 return pid; }