diff --git a/process(800-1200).cpp b/process(800-1200).cpp new file mode 100644 index 0000000..32abce8 --- /dev/null +++ b/process(800-1200).cpp @@ -0,0 +1,426 @@ +```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; +} \ No newline at end of file