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