zengqi 1 year ago
commit 5a03754018

@ -0,0 +1,460 @@
STATIC UINT32 OsLoadUserInit(LosProcessCB *processCB)
{
/* userInitTextStart -----
* | user text |//定义起始位置的指针变量//
*
* | user data | initSize
* userInitBssStart ---//定义结束位置的指针变量//
* | user bss | initBssSize
* userInitEnd --- -----
*/
errno_t errRet;
INT32 ret;
CHAR *userInitTextStart = (CHAR *)&__user_init_entry;
CHAR *userInitBssStart = (CHAR *)&__user_init_bss;
CHAR *userInitEnd = (CHAR *)&__user_init_end;
UINT32 initBssSize = userInitEnd - userInitBssStart;//计算 BSS 段(未初始化数据段)的大小 initBssSize//
UINT32 initSize = userInitEnd - userInitTextStart;//计算和整个初始化段(包括 text、data 和 bss的大小 //
VOID *userBss = NULL;
VOID *userText = NULL;
if ((LOS_Align((UINTPTR)userInitTextStart, PAGE_SIZE) != (UINTPTR)userInitTextStart) ||
(LOS_Align((UINTPTR)userInitEnd, PAGE_SIZE) != (UINTPTR)userInitEnd)) {
return LOS_EINVAL;//检查 userInitTextStart 和 userInitEnd 是否都按页对齐//
}
if ((initSize == 0) || (initSize <= initBssSize)) {
return LOS_EINVAL;//检查 initSize 是否为零或者小于等于 initBssSize如果是则返回错误码 LOS_EINVAL//
}
userText = LOS_PhysPagesAllocContiguous(initSize >> PAGE_SHIFT);
if (userText == NULL) {
return LOS_NOK;//使用 LOS_PhysPagesAllocContiguous 函数为用户空间初始化段分配连续的物理页面,并将地址赋值给 userText//
}
errRet = memcpy_s(userText, initSize, (VOID *)&__user_init_load_addr, initSize - initBssSize);
if (errRet != EOK) {
PRINT_ERR("Load user init text, data and bss failed! err : %d\n", errRet);
goto ERROR;//使用 memcpy_s 将初始化段的 text 和 data 部分从 __user_init_load_addr 复制到新分配的 userText 指向的内存区域//
}
ret = LOS_VaddrToPaddrMmap(processCB->vmSpace, (VADDR_T)(UINTPTR)userInitTextStart, LOS_PaddrQuery(userText),
initSize, VM_MAP_REGION_FLAG_PERM_READ | VM_MAP_REGION_FLAG_PERM_WRITE |
VM_MAP_REGION_FLAG_FIXED | VM_MAP_REGION_FLAG_PERM_EXECUTE |
VM_MAP_REGION_FLAG_PERM_USER);
if (ret < 0) {
PRINT_ERR("Mmap user init text, data and bss failed! err : %d\n", ret);
goto ERROR;//使用 LOS_VaddrToPaddrMmap 函数将新分配的物理页面映射到进程的虚拟地址空间//
}
/* The User init boot segment may not actually exist */
if (initBssSize != 0) {
userBss = (VOID *)((UINTPTR)userText + userInitBssStart - userInitTextStart);
errRet = memset_s(userBss, initBssSize, 0, initBssSize);
if (errRet != EOK) {
PRINT_ERR("memset user init bss failed! err : %d\n", errRet);
goto ERROR;//如果存在 BSS 段initBssSize 不为 0则使用 memset_s 函数将 BSS 段的内存清零//
}
}
return LOS_OK;
ERROR:
(VOID)LOS_PhysPagesFreeContiguous(userText, initSize >> PAGE_SHIFT);
return LOS_NOK;
}
LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
{
UINT32 ret;
UINT32 size;
TSK_INIT_PARAM_S param = { 0 };
VOID *stack = NULL;
LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess);
ret = OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY);
if (ret != LOS_OK) {
return ret;
}
ret = OsLoadUserInit(processCB);
if (ret != LOS_OK) {
goto ERROR;
}
stack = OsUserInitStackAlloc(processCB, &size);
if (stack == NULL) {
PRINT_ERR("Alloc user init process user stack failed!\n");
goto ERROR;//如果在复制或内存映射过程中发生错误,会跳转到 ERROR 标签处理错误情况,释放已分配资源并返回错误码//
}
param.pfnTaskEntry = (TSK_ENTRY_FUNC)(CHAR *)&__user_init_entry;
param.userParam.userSP = (UINTPTR)stack + size;
param.userParam.userMapBase = (UINTPTR)stack;
param.userParam.userMapSize = size;
param.uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
ret = OsUserInitProcessStart(g_userInitProcess, &param);
if (ret != LOS_OK) {
(VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);
goto ERROR;
}
return LOS_OK;//如果一切顺利,函数最后返回 LOS_OK表示用户空间初始化程序加载成功//
ERROR:
OsDeInitPCB(processCB);//在发生错误时,调用此函数来清理进程控制块//
return ret;//返回错误码//
}
STATIC UINT32 OsCopyUser(LosProcessCB *childCB, LosProcessCB *parentCB)
{
#ifdef LOSCFG_SECURITY_CAPABILITY//执行用户信息的复制//
UINT32 size = sizeof(User) + sizeof(UINT32) * (parentCB->user->groupNumber - 1);//算需要复制的用户信息所需的内存大小//
childCB->user = LOS_MemAlloc(m_aucSysMem1, size);//为子进程分配内存来存储用户信息//
if (childCB->user == NULL) {
return LOS_ENOMEM;//如果分配失败,返回 LOS_ENOMEM 表示内存不足//
}
(VOID)memcpy_s(childCB->user, size, parentCB->user, size);//使用 memcpy_s 将父进程的用户信息复制到子进程//
#endif
return LOS_OK;//返回 LOS_OK 表示成功//
}
STATIC VOID OsInitCopyTaskParam(LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size,
TSK_INIT_PARAM_S *childPara)
{
LosTaskCB *mainThread = NULL;
UINT32 intSave;//初始化子进程的任务参数//
SCHEDULER_LOCK(intSave);
mainThread = OsCurrTaskGet();//锁定调度器以保证线程安全//
if (OsProcessIsUserMode(childProcessCB)) {
childPara->pfnTaskEntry = mainThread->taskEntry;
childPara->uwStackSize = mainThread->stackSize;
childPara->userParam.userArea = mainThread->userArea;
childPara->userParam.userMapBase = mainThread->userMapBase;
childPara->userParam.userMapSize = mainThread->userMapSize;//根据子进程是否为用户模式,设置任务入口点、堆栈大小以及其他用户特定的参数//
} else {
childPara->pfnTaskEntry = (TSK_ENTRY_FUNC)entry;
childPara->uwStackSize = size;
}
childPara->pcName = (CHAR *)name;
childPara->policy = mainThread->policy;
childPara->usTaskPrio = mainThread->priority;
childPara->processID = childProcessCB->processID;//设置任务名称、调度策略、优先级等信息//
if (mainThread->taskStatus & OS_TASK_FLAG_PTHREAD_JOIN) {
childPara->uwResved = OS_TASK_FLAG_PTHREAD_JOIN;
} else if (mainThread->taskStatus & OS_TASK_FLAG_DETACHED) {
childPara->uwResved = OS_TASK_FLAG_DETACHED;//如果当前任务支持线程的 join 操作或者是 detached 状态,则相应地设置标志位//
}
SCHEDULER_UNLOCK(intSave);//解锁调度器//
}
STATIC UINT32 OsCopyTask(UINT32 flags, LosProcessCB *childProcessCB, const CHAR *name, UINTPTR entry, UINT32 size)
{//创建一个新的任务,作为子进程的主线程//
LosTaskCB *runTask = OsCurrTaskGet();
TSK_INIT_PARAM_S childPara = { 0 };
UINT32 ret;
UINT32 intSave;
UINT32 taskID;
OsInitCopyTaskParam(childProcessCB, name, entry, size, &childPara);
ret = LOS_TaskCreateOnly(&taskID, &childPara);//调用 LOS_TaskCreateOnly 来创建任务,仅创建任务而不立即运行//
if (ret != LOS_OK) {
if (ret == LOS_ERRNO_TSK_TCB_UNAVAILABLE) {
return LOS_EAGAIN;
}
return LOS_ENOMEM;//如果任务创建失败,根据错误类型返回相应的错误码(如 LOS_EAGAIN 表示资源暂时不可用LOS_ENOMEM 表示内存不足)//
}
LosTaskCB *childTaskCB = OS_TCB_FROM_TID(taskID);//获取新创建任务的任务控制块指针//
childTaskCB->taskStatus = runTask->taskStatus;
if (childTaskCB->taskStatus & OS_TASK_STATUS_RUNNING) {
childTaskCB->taskStatus &= ~OS_TASK_STATUS_RUNNING;
} else {
if (OS_SCHEDULER_ACTIVE) {
LOS_Panic("Clone thread status not running error status: 0x%x\n", childTaskCB->taskStatus);
}//如果子任务的状态为运行状态,则清除运行状态位//
childTaskCB->taskStatus &= ~OS_TASK_STATUS_UNUSED;
childProcessCB->priority = OS_PROCESS_PRIORITY_LOWEST;//如果调度器处于激活状态并且子任务不在运行状态,触发内核恐慌//
}
if (OsProcessIsUserMode(childProcessCB)) {
SCHEDULER_LOCK(intSave);
OsUserCloneParentStack(childTaskCB->stackPointer, runTask->topOfStack, runTask->stackSize);
SCHEDULER_UNLOCK(intSave);
}
return LOS_OK;
}
STATIC UINT32 OsCopyParent(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
{
UINT32 ret;
UINT32 intSave;
LosProcessCB *parentProcessCB = NULL;
SCHEDULER_LOCK(intSave);//锁定调度器以保证线程安全//
childProcessCB->priority = runProcessCB->priority;
if (flags & CLONE_PARENT) {
parentProcessCB = OS_PCB_FROM_PID(runProcessCB->parentProcessID);
} else {
parentProcessCB = runProcessCB;
}//根据 flags 中的 CLONE_PARENT 位决定子进程的父进程是当前进程的父进程还是当前进程本身//
childProcessCB->parentProcessID = parentProcessCB->processID;
LOS_ListTailInsert(&parentProcessCB->childrenList, &childProcessCB->siblingList);
childProcessCB->group = parentProcessCB->group;
LOS_ListTailInsert(&parentProcessCB->group->processList, &childProcessCB->subordinateGroupList);
ret = OsCopyUser(childProcessCB, parentProcessCB);//调用 OsCopyUser 函数复制用户信息//
SCHEDULER_UNLOCK(intSave);//解锁调度器//
return ret;
}
STATIC UINT32 OsCopyMM(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
{
status_t status;
UINT32 intSave;
if (!OsProcessIsUserMode(childProcessCB)) {
return LOS_OK;//如果子进程不是用户模式,直接返回 LOS_OK//
}
if (flags & CLONE_VM) {
SCHEDULER_LOCK(intSave);
childProcessCB->vmSpace->archMmu.virtTtb = runProcessCB->vmSpace->archMmu.virtTtb;
childProcessCB->vmSpace->archMmu.physTtb = runProcessCB->vmSpace->archMmu.physTtb;
SCHEDULER_UNLOCK(intSave);
return LOS_OK;//如果 flags 中的 CLONE_VM 位被设置,表示需要共享虚拟内存空间,那么将父进程的虚拟内存表指针复制给子进程,并返回 LOS_OK//
}
status = LOS_VmSpaceClone(runProcessCB->vmSpace, childProcessCB->vmSpace);
if (status != LOS_OK) {
return LOS_ENOMEM;
}
return LOS_OK;//如果没有设置 CLONE_VM 位,则调用 LOS_VmSpaceClone 函数来克隆父进程的虚拟内存空间给子进程//
}
STATIC UINT32 OsCopyFile(UINT32 flags, LosProcessCB *childProcessCB, LosProcessCB *runProcessCB)
{
#ifdef LOSCFG_FS_VFS
if (flags & CLONE_FILES) {
childProcessCB->files = runProcessCB->files;
} else {
childProcessCB->files = dup_fd(runProcessCB->files);
}
if (childProcessCB->files == NULL) {
return LOS_ENOMEM;//如果虚拟内存空间克隆失败,返回 LOS_ENOMEM 表示内存不足//
}
#endif
childProcessCB->consoleID = runProcessCB->consoleID;
childProcessCB->umask = runProcessCB->umask;
return LOS_OK;
}
STATIC UINT32 OsForkInitPCB(UINT32 flags, LosProcessCB *child, const CHAR *name, UINTPTR sp, UINT32 size)
{//初始化子进程的进程控制块PCB//
UINT32 ret;
LosProcessCB *run = OsCurrProcessGet();
ret = OsInitPCB(child, run->processMode, OS_PROCESS_PRIORITY_LOWEST, name);
if (ret != LOS_OK) {
return ret;
}//调用 OsInitPCB 来初始化 PCB 的基本信息//
ret = OsCopyParent(flags, child, run);
if (ret != LOS_OK) {
return ret;
}
return OsCopyTask(flags, child, name, sp, size);//继续调用 OsCopyParent 复制父进程的某些资源给子进程,最后调用 OsCopyTask 来复制任务相关的资源//
}
STATIC UINT32 OsChildSetProcessGroupAndSched(LosProcessCB *child, LosProcessCB *run)
{//用于将子进程设置到正确的进程组,并将其加入到调度队列中//
UINT32 intSave;
UINT32 ret;
ProcessGroup *group = NULL;
SCHEDULER_LOCK(intSave);
if (run->group->groupID == OS_USER_PRIVILEGE_PROCESS_GROUP) {
ret = OsSetProcessGroupIDUnsafe(child->processID, child->processID, &group);
if (ret != LOS_OK) {
SCHEDULER_UNLOCK(intSave);
return LOS_ENOMEM;
}
}//如果父进程属于用户特权进程组,则会为子进程创建一个新的进程组//
OsSchedTaskEnQueue(OS_TCB_FROM_TID(child->threadGroupID));
SCHEDULER_UNLOCK(intSave);
(VOID)LOS_MemFree(m_aucSysMem1, group);
return LOS_OK;//将子进程的主线程加入调度队列,并释放之前可能分配的进程组内存//
}
STATIC UINT32 OsCopyProcessResources(UINT32 flags, LosProcessCB *child, LosProcessCB *run)
{//负责复制父进程的资源给子进程,包括内存管理单元、文件描述符等//
UINT32 ret;
ret = OsCopyMM(flags, child, run);
if (ret != LOS_OK) {
return ret;
}
ret = OsCopyFile(flags, child, run);
if (ret != LOS_OK) {
return ret;
}//如果系统配置了 LOSCFG_KERNEL_LITEIPC则还需要重新初始化 IPC 资源//
#ifdef LOSCFG_KERNEL_LITEIPC
if (OsProcessIsUserMode(child)) {
ret = LiteIpcPoolReInit(&child->ipcInfo, (const ProcIpcInfo *)(&run->ipcInfo));
if (ret != LOS_OK) {
return LOS_ENOMEM;
}
}
#endif
#ifdef LOSCFG_SECURITY_CAPABILITY
OsCopyCapability(run, child);
#endif
return LOS_OK;//如果配置了 LOSCFG_SECURITY_CAPABILITY还需要复制安全能力//
}
STATIC INT32 OsCopyProcess(UINT32 flags, const CHAR *name, UINTPTR sp, UINT32 size)
{
UINT32 intSave, ret, processID;
LosProcessCB *run = OsCurrProcessGet();
LosProcessCB *child = OsGetFreePCB();
if (child == NULL) {
return -LOS_EAGAIN;
}
processID = child->processID;//获取一个空闲的 PCB然后通过调用 OsForkInitPCB 初始化 PCB//
ret = OsForkInitPCB(flags, child, name, sp, size);
if (ret != LOS_OK) {
goto ERROR_INIT;
}
ret = OsCopyProcessResources(flags, child, run);
if (ret != LOS_OK) {
goto ERROR_TASK;
}//通过 OsCopyProcessResources 复制资源//
ret = OsChildSetProcessGroupAndSched(child, run);
if (ret != LOS_OK) {
goto ERROR_TASK;
}
LOS_MpSchedule(OS_MP_CPU_ALL);
if (OS_SCHEDULER_ACTIVE) {
LOS_Schedule();
}
return processID;//通过 OsChildSetProcessGroupAndSched 设置进程组和调度。如果任何步骤失败,它会跳转到错误处理部分并释放已分配的资源//
ERROR_TASK:
SCHEDULER_LOCK(intSave);
(VOID)OsTaskDeleteUnsafe(OS_TCB_FROM_TID(child->threadGroupID), OS_PRO_EXIT_OK, intSave);//调用来删除已经创建但未能成功完成初始化的子进程的主线程//
ERROR_INIT:
OsDeInitPCB(child);
return -ret;//调用来释放和反初始化进程控制块PCB//
}
LITE_OS_SEC_TEXT INT32 OsClone(UINT32 flags, UINTPTR sp, UINT32 size)
{
UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_VM;
if (flags & (~cloneFlag)) {
PRINT_WARN("Clone dont support some flags!\n");//检查传入的 flags 参数,并确保没有不支持的标志被设置。如果有不支持的标志,它会打印警告//
}
return OsCopyProcess(cloneFlag & flags, NULL, sp, size);//调用 OsCopyProcess 来实际创建一个新的进程或线程//
}
LITE_OS_SEC_TEXT INT32 LOS_Fork(UINT32 flags, const CHAR *name, const TSK_ENTRY_FUNC entry, UINT32 stackSize)
{//供了一个创建新进程的接口,类似于 UNIX 系统中的 fork 系统调用//
UINT32 cloneFlag = CLONE_PARENT | CLONE_THREAD | CLONE_VFORK | CLONE_FILES;
if (flags & (~cloneFlag)) {
PRINT_WARN("Clone dont support some flags!\n");
}//检查 flags 参数,确保没有不支持的标志被设置,并添加 CLONE_FILES 标志,以便子进程可以共享文件描述符表//
flags |= CLONE_FILES;
return OsCopyProcess(cloneFlag & flags, name, (UINTPTR)entry, stackSize);
}
#else
LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
{
return 0;
}
#endif//OsCopyProcess 函数来创建一个新的进程//
LITE_OS_SEC_TEXT VOID LOS_Exit(INT32 status)
{//允许一个进程退出并释放资源//
UINT32 intSave;
/* The exit of a kernel - state process must be kernel - state and all threads must actively exit */
LosProcessCB *processCB = OsCurrProcessGet();
SCHEDULER_LOCK(intSave);//如果当前进程是内核态进程且拥有多个线程,则不允许直接退出//
if (!OsProcessIsUserMode(processCB) && (processCB->threadNumber != 1)) {
SCHEDULER_UNLOCK(intSave);
PRINT_ERR("Kernel-state processes with multiple threads are not allowed to exit directly\n");
return;
}
SCHEDULER_UNLOCK(intSave);
OsTaskExitGroup((UINT32)status);
OsProcessExit(OsCurrTaskGet(), (UINT32)status);//如果条件允许,它会调用 OsTaskExitGroup 和 OsProcessExit 来完成退出流程//
}
LITE_OS_SEC_TEXT INT32 LOS_GetUsedPIDList(UINT32 *pidList, INT32 pidMaxNum)
{//这个函数用于获取当前正在使用的所有进程的 PID 列表//
LosProcessCB *pcb = NULL;
INT32 num = 0;
UINT32 intSave;
UINT32 pid = 1;
if (pidList == NULL) {
return 0;
}//它通过遍历所有可能的 PID 并检查对应的 PCB 是否正在使用来实现//
SCHEDULER_LOCK(intSave);
while (OsProcessIDUserCheckInvalid(pid) == false) {
pcb = OS_PCB_FROM_PID(pid);
pid++;
if (OsProcessIsUnused(pcb)) {
continue;
}
pidList[num] = pcb->processID;
num++;
if (num >= pidMaxNum) {
break;
}
}
SCHEDULER_UNLOCK(intSave);
return num;//如果 PCB 正在使用,它将该 PCB 的 PID 添加到 pidList 数组中,并返回找到的 PID 数量//
}
#ifdef LOSCFG_FS_VFS
LITE_OS_SEC_TEXT struct fd_table_s *LOS_GetFdTable(UINT32 pid)
{//返回指定 PID 的进程的文件描述符表//
LosProcessCB *pcb = NULL;
struct files_struct *files = NULL;//它首先检查 PID 是否有效,然后获取对应的 PCB 和文件结构体 files//
if (OS_PID_CHECK_INVALID(pid)) {
return NULL;
}
pcb = OS_PCB_FROM_PID(pid);
files = pcb->files;
if (files == NULL) {
return NULL;
}
return files->fdt;//如果这些结构体有效,它返回文件描述符表 fdt//
}

@ -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;
}

Binary file not shown.
Loading…
Cancel
Save