class="hide-preCode-box">
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
2.2 进程创建初始化函数OsProcessCreateInit
该函数用于创建进程时的一些初始化操作 ,主要是文件系统、安全能力、进程组等等。需要3个参数,分别是进程控制块指针,标记用户态还是内核态进程的flags,进程名称name。首先执行⑴调用OsInitPCB()对进程控制块进行初始化,然后,如果配置支持了虚拟文件系统VFS,则执行⑵为进程分别文件。⑶处根据进程号创建进程组。如果支持安全能力,则执行⑷创建用户。如果初始化失败,会执行⑸恢复进程控制块到初始化之前的状态。
STATIC UINT32 OsProcessCreateInit(LosProcessCB *processCB, UINT32 flags, const CHAR *name)
{
ProcessGroup *group = NULL;
⑴ UINT32 ret = OsInitPCB(processCB, flags, name);
if (ret != LOS_OK) {
goto EXIT;
}
#ifdef LOSCFG_FS_VFS
⑵ processCB->files = alloc_files();
if (processCB->files == NULL) {
ret = LOS_ENOMEM;
goto EXIT;
}
#endif
⑶ group = OsCreateProcessGroup(processCB->processID);
if (group == NULL) {
ret = LOS_ENOMEM;
goto EXIT;
}
#ifdef LOSCFG_SECURITY_CAPABILITY
⑷ processCB->user = OsCreateUser(0, 0, 1);
if (processCB->user == NULL) {
ret = LOS_ENOMEM;
goto EXIT;
}
#endif
return LOS_OK;
EXIT:
⑸ OsDeInitPCB(processCB);
return ret;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
2.3 系统进程创建函数OsSystemProcessCreate
接下来,我们看看系统进程创建函数OsSystemProcessCreate的源代码。⑴处开始先后调用OsProcessInit、OsProcessCreateInit初始化内核态根进程,⑵处进程的状态不再是初始化状态。⑶处从内核进程获取全局进程组指针g_processGroup,然后初始化进程组的双向链表。这样看来,所有的进程组都会挂载到内核进程的进程组节点上。⑷处初始化内核空闲进程,内核空闲进程的父进程也是内核态根进程,插入到进程组链表,设置空闲进程的状态不再是初始化状态。执行⑸创建空闲任务,然后设置空闲进程的线程组编号为空闲线程编号。
LITE_OS_SEC_TEXT_INIT UINT32 OsSystemProcessCreate(VOID)
{
⑴ UINT32 ret = OsProcessInit();
if (ret != LOS_OK) {
return ret;
}
LosProcessCB *kerInitProcess = OS_PCB_FROM_PID(g_kernelInitProcess);
ret = OsProcessCreateInit(kerInitProcess, OS_KERNEL_MODE, "KProcess");
if (ret != LOS_OK) {
return ret;
}
⑵ kerInitProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;
⑶ g_processGroup = kerInitProcess->group;
LOS_ListInit(&g_processGroup->groupList);
⑷ LosProcessCB *idleProcess = OS_PCB_FROM_PID(g_kernelIdleProcess);
ret = OsInitPCB(idleProcess, OS_KERNEL_MODE, "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
idleProcess->processStatus &= ~OS_PROCESS_STATUS_INIT;
⑸ ret = OsIdleTaskCreate();
if (ret != LOS_OK) {
return ret;
}
idleProcess->threadGroupID = OsGetIdleTaskId();
return LOS_OK;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
3. LiteOS-A内核用户进程创建函数OsUserInitProcess
系统启动阶段,OsUserInitProcess启动init进程。该函数在device开发板目录下系统初始化文件中调用,如system_init.c等等。该函数需要开启LOSCFG_KERNEL_DYNLOAD宏,否则函数体内容为空。在阅读函数OsUserInitProcess的源码前,先看看该函数调用的其他函数,如OsLoadUserInit、OsUserInitStackAlloc、OsUserInitProcessStart等等。
3.1 加载用户初始化数据函数OsLoadUserInit
该函数用于加载用户数据。⑴处从链接脚本获取text、bss的开启和结束地址,然后计算bss段、初始化段的大小。⑵处进行一些必要的校验,是否针对内存页对齐,内存段长度是否合理等。然后执行⑶,申请物理内存页,然后把用户初始化数据复制到申请的内存页。⑷处进行虚实映射。如果bss段长度不为0,执行⑸把bss段的内存区域清零。
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;
UINT32 initSize = userInitEnd - userInitTextStart;
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;
}
if ((initSize == 0) || (initSize <= initBssSize)) {
return LOS_EINVAL;
}
⑶ userText = LOS_PhysPagesAllocContiguous(initSize >> PAGE_SHIFT);
if (userText == NULL) {
return LOS_NOK;
}
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;
}
⑷ 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;
}
/* 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;
}
}
return LOS_OK;
ERROR:
(VOID)LOS_PhysPagesFreeContiguous(userText, initSize >> PAGE_SHIFT);
return LOS_NOK;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
3.2 用户初始化栈函数OsUserInitStackAlloc
该函数需要2个参数,第一个参数为进程控制块,第二个参数为输出参数,用于获取用户任务栈的大小。⑴处用户任务栈大小对页进行对齐,然后申请内存区域,然后执行⑵设置内存区域类型,并社区内存区域标签为栈。然后设置输出参数为任务栈大小,并返回用户栈空间的开始地址。
STATIC VOID *OsUserInitStackAlloc(LosProcessCB *processCB, UINT32 *size)
{
LosVmMapRegion *region = NULL;
⑴ UINT32 stackSize = ALIGN(OS_USER_TASK_STACK_SIZE, PAGE_SIZE);
region = LOS_RegionAlloc(processCB->vmSpace, 0, stackSize,
VM_MAP_REGION_FLAG_PERM_USER | VM_MAP_REGION_FLAG_PERM_READ |
VM_MAP_REGION_FLAG_PERM_WRITE, 0);
if (region == NULL) {
return NULL;
}
⑵ LOS_SetRegionTypeAnon(region);
region->regionFlags |= VM_MAP_REGION_FLAG_STACK;
*size = stackSize;
return (VOID *)(UINTPTR)region->range.base;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
3.3 用户进程初始化开启函数OsUserInitProcessStart
用户进程初始化开启函数OsUserInitProcessStart用于创建线程,设置调度策略等。⑴处为用户态进程创建个线程,然后为进程设置优先级。⑵处设置进程状态为非初始化状态,然后执行⑶为任务设置调度策略和优先级。
STATIC UINT32 OsUserInitProcessStart(LosProcessCB *processCB, TSK_INIT_PARAM_S *param)
{
UINT32 intSave;
INT32 ret;
⑴ UINT32 taskID = OsCreateUserTask(processCB->processID, param);
if (taskID == OS_INVALID_VALUE) {
return LOS_NOK;
}
ret = LOS_SetProcessPriority(processCB->processID, OS_PROCESS_USERINIT_PRIORITY);
if (ret != LOS_OK) {
PRINT_ERR("User init process set priority failed! ERROR:%d \n", ret);
goto EXIT;
}
SCHEDULER_LOCK(intSave);
⑵ processCB->processStatus &= ~OS_PROCESS_STATUS_INIT;
SCHEDULER_UNLOCK(intSave);
⑶ ret = LOS_SetTaskScheduler(taskID, LOS_SCHED_RR, OS_TASK_PRIORITY_LOWEST);
if (ret != LOS_OK) {
PRINT_ERR("User init process set scheduler failed! ERROR:%d \n", ret);
goto EXIT;
}
return LOS_OK;
EXIT:
(VOID)LOS_TaskDelete(taskID);
return ret;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
3.4 用户态进程初始化函数OsUserInitProcess
用户态进程初始化函数OsUserInitProcess完成用户态进程的初始化。⑴处获取用户态根进程,然后调用函数创建用户态根进程,并调用函数OsLoadUserInit加载用户初始化数据。⑵处初始化用户栈,然后设置线程的初始化参数,⑶处完成用户态进程的创建。
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");
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;
}
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(processCB, ¶m);
if (ret != LOS_OK) {
(VOID)OsUnMMap(processCB->vmSpace, param.userParam.userMapBase, param.userParam.userMapSize);
goto ERROR;
}
return LOS_OK;
ERROR:
OsDeInitPCB(processCB);
return ret;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
小结
本文介绍了进程管理的内核进程、用户态进程的初始化相关函数。
如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:
搭建开发环境 Windows 开发环境的搭建 Ubuntu 开发环境搭建 Linux 与 Windows 之间的文件共享 ……
构建子系统 启动流程 子系统 分布式任务调度子系统 分布式通信子系统 驱动子系统 ……
写在最后
如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙: 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://qr21.cn/FV7h05
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/maniuT/article/details/139664197","extend1":"pc","ab":"new"}">>
id="blogExtensionBox" style="width:400px;margin:auto;margin-top:12px" class="blog-extension-box"> class="blog_extension blog_extension_type2" id="blog_extension">
class="extension_official" data-report-click="{"spm":"1001.2101.3001.6471"}" data-report-view="{"spm":"1001.2101.3001.6471"}">
class="blog_extension_card_left">
class="blog_extension_card_cont">
鸿蒙开发学习资料领取!!!
class="blog_extension_card_cont_r">
微信名片
评论记录:
回复评论: