You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ruanjiangongcheng/process(800-1200).cpp

426 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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