鸿蒙轻内核A核源码分析系列七 进程管理 (2)

往期知识点记录:

本文先熟悉下进程管理的文件kernel\base\core\los_process.c中的内部接口,读读代码,做些记录。

1、LiteOS-A内核进程全局变量

⑴是进程池,存放各个进程控制块LosProcessCB的信息。⑵处开始的g_freeProcess是空闲进程链表,挂载各个空闲进程控制块;g_processRecycleList是待回收进程控制块链表,挂载各个等待回收的进程控制块。⑶处开始的g_userInitProcess是用户根进程的进程号,数值固定为1.,g_kernelInitProcess是内核进程,内核进程的进程号固定为2,g_kernelIdleProcess是内核空闲进程,进程号固定为0。⑷处开始的g_processMaxNum表示为配置的进程的最大数目,g_processGroup维护进程组信息,所有的进程组都会挂载这个全局进程组链表节点g_processGroup->groupList上。

⑴  LITE_OS_SEC_BSS LosProcessCB *g_processCBArray = NULL;
⑵  LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_freeProcess;
    LITE_OS_SEC_DATA_INIT STATIC LOS_DL_LIST g_processRecycleList;
⑶  LITE_OS_SEC_BSS UINT32 g_userInitProcess = OS_INVALID_VALUE;
    LITE_OS_SEC_BSS UINT32 g_kernelInitProcess = OS_INVALID_VALUE;
    LITE_OS_SEC_BSS UINT32 g_kernelIdleProcess = OS_INVALID_VALUE;
⑷  LITE_OS_SEC_BSS UINT32 g_processMaxNum;
    LITE_OS_SEC_BSS ProcessGroup *g_processGroup = NULL;

2. 涉及空闲进程链表内部操作

空闲进程块链接操作涉及初始化OsProcessInit、插入空闲链接OsInsertPCBToFreeList、从链表获取空闲进程块OsGetFreePCB。我们先看下OsInsertPCBToFreeList和OsGetFreePCB。初始化链表在初始化进程时再看。

2.1 OsInsertPCBToFreeList

OsInsertPCBToFreeList函数会进程控制块插入到空闲进程块链表。函数比较简单,把进程结构体块清空,然后放入进程块链表。有个有意思的细节需要了解下。⑴处记录下进程号,然后把进程块置空。⑵处又把进程号设置给进程块结构体,进程号数量是固定的。⑶处开始设置进程为未使用状态,更新定时器编号未无效值,然后插入到空闲进程块链表。

    STATIC INLINE VOID OsInsertPCBToFreeList(LosProcessCB *processCB)
    {
⑴      UINT32 pid = processCB->processID;
        (VOID)memset_s(processCB, sizeof(LosProcessCB), 0, sizeof(LosProcessCB));
⑵      processCB->processID = pid;
⑶      processCB->processStatus = OS_PROCESS_FLAG_UNUSED;
        processCB->timerID = (timer_t)(UINTPTR)MAX_INVALID_TIMER_VID;
        LOS_ListTailInsert(&g_freeProcess, &processCB->pendList);
    }

2.2 OsGetFreePCB

OsGetFreePCB函数用于从空闲进程链表中获取进程块,该函数只有在开启LOSCFG_KERNEL_VM的时候才生效。⑴处当空闲进程链表为空时,返回NULL。⑵处获取空闲进程块指针,然后虫空闲进程块链表中删除。

STATIC LosProcessCB *OsGetFreePCB(VOID)
{
    LosProcessCB *processCB = NULL;
    UINT32 intSave;

    SCHEDULER_LOCK(intSave);
⑴  if (LOS_ListEmpty(&g_freeProcess)) {
        SCHEDULER_UNLOCK(intSave);
        PRINT_ERR("No idle PCB in the system!\n");
        return NULL;
    }

⑵  processCB = OS_PCB_FROM_PENDLIST(LOS_DL_LIST_FIRST(&g_freeProcess));
    LOS_ListDelete(&processCB->pendList);
    SCHEDULER_UNLOCK(intSave);

    return processCB;
}

3. 涉及进程和线程的内部操作

该类操作包含把线程从进程中删除OsDeleteTaskFromProcess,还包括把线程包含进进程OsProcessAddNewTask。

3.1 OsDeleteTaskFromProcess

OsDeleteTaskFromProcess函数用于从进程中删除一个线程。⑴处可以看出每个线程/任务控制块都维护进程号,根据进程号可以获取进程控制块。每个线程控制块通过自己的成员变量threadList挂载到进程的线程链表上。⑵处从进程的线程链表上删除,然后把进程的线程数减去1。

⑶处把任务控制块插入到待回收链表上。

    VOID OsDeleteTaskFromProcess(LosTaskCB *taskCB)
    {
⑴      LosProcessCB *processCB = OS_PCB_FROM_PID(taskCB->processID);

⑵      LOS_ListDelete(&taskCB->threadList);
        processCB->threadNumber--;
⑶      OsTaskInsertToRecycleList(taskCB);
    }

3.2 OsProcessAddNewTask

函数OsProcessAddNewTask把线程关联到进程上,需要两个参数,分别进程号和线程控制块。需要注意返回值,返回值表示,关联新线程之前的,进程的线程数量。⑴处获取进程块,⑵处把线程块关联的进程号设置为参数中输入的进程号,然后把线程控制块挂载到进程的线程链表上。可以看出,线程块的threadList用于挂载到进程的线程链表,进程块的threadSiblingList节点用于挂载本进程下的各种线程。⑶处如果是用户态进程,标记线程的状态为用户态线程。⑷如果进程的线程数目大于0,线程的基础优先级basePrio设置为和进程的主线程的优先级一样,否则设置为最大优先级。⑸如果是内核进程,线程的基础优先级设置为当前线程的优先级。⑹处如果开启了虚拟内存,设置线程的MMU结构体信息为进程虚拟地址空间中维护的MMU。⑺处如果进程的线程数为0,则把线程设置为进程的主线程。然后把进程的线程数加1。⑻处获得进程已有的线程数量,然后把进程的线程数量增加1。然后返回进程的关联新线程之前的线程数量。

    UINT32 OsProcessAddNewTask(UINT32 pid, LosTaskCB *taskCB)
    {
        UINT32 intSave;
        UINT16 numCount;
⑴      LosProcessCB *processCB = OS_PCB_FROM_PID(pid);

        SCHEDULER_LOCK(intSave);
⑵      taskCB->processID = pid;
        LOS_ListTailInsert(&(processCB->threadSiblingList), &(taskCB->threadList));

⑶      if (OsProcessIsUserMode(processCB)) {
            taskCB->taskStatus |= OS_TASK_FLAG_USER_MODE;
⑷          if (processCB->threadNumber > 0) {
                taskCB->basePrio = OS_TCB_FROM_TID(processCB->threadGroupID)->basePrio;
            } else {
                taskCB->basePrio = OS_USER_PROCESS_PRIORITY_HIGHEST;
            }
        } else {
⑸           taskCB->basePrio = OsCurrTaskGet()->basePrio;
        }

    #ifdef LOSCFG_KERNEL_VM
⑹      taskCB->archMmu = (UINTPTR)&processCB->vmSpace->archMmu;
    #endif
        if (!processCB->threadNumber) {
⑺          processCB->threadGroupID = taskCB->taskID;
        }
        processCB->threadNumber++;

⑻      numCount = processCB->threadCount;
        processCB->threadCount++;
        SCHEDULER_UNLOCK(intSave);
        return numCount;
    }

4、涉及进程组的内部操作

涉及进程组的内部操作包含进程组的创建OsCreateProcessGroup、进程组的退出OsExitProcessGroup、查找进程组OsExitProcessGroup。

4.1 OsCreateProcessGroup

OsCreateProcessGroup函数用于根据进程号创建进程组,返回值为创建的进程组指针。进程组是动态创建的,⑴处为进程组控制块申请动态内存。⑵处进程组的groupId即为创建进程组的进程号,接着初始化进程组的两个链表。⑶处获取进程控制块,然后执行⑷把进程挂载到进程组的processList进程链表上,使用的挂载点为进程控制块的subordinateGroupList链表节点,所以看到这个成员变量,要想起来是在同一个进程组的各个进程的链接关系。然后更新进程的进程组信息,并更新进程状态为进程组leader。⑸处如果存在全局进程组,则把创建的进程组挂载到全局进程组变量上。

    STATIC ProcessGroup *OsCreateProcessGroup(UINT32 pid)
    {
        LosProcessCB *processCB = NULL;
⑴      ProcessGroup *group = LOS_MemAlloc(m_aucSysMem1, sizeof(ProcessGroup));
        if (group == NULL) {
            return NULL;
        }

⑵      group->groupID = pid;
        LOS_ListInit(&group->processList);
        LOS_ListInit(&group->exitProcessList);

⑶      processCB = OS_PCB_FROM_PID(pid);
⑷      LOS_ListTailInsert(&group->processList, &processCB->subordinateGroupList);
        processCB->group = group;
        processCB->processStatus |= OS_PROCESS_FLAG_GROUP_LEADER;
⑸      if (g_processGroup != NULL) {
            LOS_ListTailInsert(&g_processGroup->groupList, &group->groupList);
        }

        return group;
    }

4.2 OsExitProcessGroup

OsExitProcessGroup函数用于把一个进程退出进程组,第一个参数指定进程控制块,第二个为输出参数,记录进程所在的进程组。⑴根据进程获取所在的进程组,然后获取进程组的主进程,然后获取主进程的进程控制块。⑵处把进程从进程组里删除。⑶处表示如果进程组下面没有挂载进程,并且进程组下面也没有挂载退出的进程,则执行⑷把进程组从全局进程组链表上删除。然后,把进程组的主进程的状态设置为非主进程OS_PROCESS_FLAG_GROUP_LEADER。⑸处如果主进程未使用状态并且主进程非退出状态,则把主进程从阻塞链表上删除,然后插入到空闲空闲进程链表上。⑹处既然进程推出了进程组,需要更新该进程的所属进程组为NULL。

    STATIC VOID OsExitProcessGroup(LosProcessCB *processCB, ProcessGroup **group)
    {
⑴      LosProcessCB *groupProcessCB = OS_PCB_FROM_PID(processCB->group->groupID);

⑵      LOS_ListDelete(&processCB->subordinateGroupList);
⑶      if (LOS_ListEmpty(&processCB->group->processList) && LOS_ListEmpty(&processCB->group->exitProcessList)) {
⑷          LOS_ListDelete(&processCB->group->groupList);
            groupProcessCB->processStatus &= ~OS_PROCESS_FLAG_GROUP_LEADER;
            *group = processCB->group;
⑸          if (OsProcessIsUnused(groupProcessCB) && !(groupProcessCB->processStatus & OS_PROCESS_FLAG_EXIT)) {
                LOS_ListDelete(&groupProcessCB->pendList);
                OsInsertPCBToFreeList(groupProcessCB);
            }
        }

⑹      processCB->group = NULL;
    }

4.3 OsFindProcessGroup

OsFindProcessGroup函数用于根据进程组编号获取进程组指针。⑴如果等于全局进程组的编号,则反正全局进程组指针。⑵处遍历全局进程组下面的各个进程组,判断遍历到的进程组的编号是否等于传入的进程组编号,如果相等则返回。如果执行到⑶,表明没有查询到指定的进程组编号的进程组信息。

    STATIC ProcessGroup *OsFindProcessGroup(UINT32 gid)
    {
        ProcessGroup *group = NULL;
⑴      if (g_processGroup->groupID == gid) {
            return g_processGroup;
        }

⑵      LOS_DL_LIST_FOR_EACH_ENTRY(group, &g_processGroup->groupList, ProcessGroup, groupList) {
            if (group->groupID == gid) {
                return group;
            }
        }

⑶      PRINT_INFO("%s is find group : %u failed!\n", __FUNCTION__, gid);
        return NULL;
    }

小结

本文介绍了进程管理的文件本文先熟悉下进程管理的文件kernel\base\core\los_process.c中的部分内部接口。

经常有很多小伙伴抱怨说:不知道学习鸿蒙开发哪些技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?

为了能够帮助到大家能够有规划的学习,这里特别整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

《鸿蒙 (Harmony OS)开发学习手册》(共计892页):https://gitcode.com/HarmonyOS_MN/733GH/overview

如何快速入门?

1.基本概念

2.构建第一个ArkTS应用

3.......

开发基础知识:

1.应用基础知识

2.配置文件

3.应用数据管理

4.应用安全管理

5.应用隐私保护

6.三方应用调用管控机制

7.资源分类与访问

8.学习ArkTS语言

9.......

基于ArkTS 开发

1.Ability开发

2.UI开发

3.公共事件与通知

4.窗口管理

5.媒体

6.安全

7.网络与链接

8.电话服务

9.数据管理

10.后台任务(Background Task)管理

11.设备管理

12.设备使用信息统计

13.DFX

14.国际化开发

15.折叠屏系列

16.......

鸿蒙开发面试真题(含参考答案):https://gitcode.com/HarmonyOS_MN/733GH/overview

OpenHarmony 开发环境搭建

《OpenHarmony源码解析》 :https://gitcode.com/HarmonyOS_MN/733GH/overview

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ......
  • 系统架构分析
  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ......

OpenHarmony 设备开发学习手册 :https://gitcode.com/HarmonyOS_MN/733GH/overview


相关推荐
redcocal1 小时前
地平线内推码 kbrfck
c++·嵌入式硬件·mcu·算法·fpga开发·求职招聘
CS小麻瓜2 小时前
Web植物管理系统-下位机部分
c++·嵌入式硬件·湖南大学
MGT_97964 小时前
基于51单片机的GPS定位系统(仿真)
单片机·嵌入式硬件·51单片机
艾格北峰4 小时前
STM32 BootLoader 刷新项目 (六) 获取帮助-命令0x52
arm开发·stm32·单片机·嵌入式硬件
m0_739312875 小时前
【STM32】独立看门狗(IWDG)原理详解及编程实践(上)
stm32·单片机·嵌入式硬件
CV金科7 小时前
蓝桥杯-STM32G431RBT6(串口)
c语言·stm32·单片机·嵌入式硬件·蓝桥杯
让开,我要吃人了8 小时前
OpenHarmony鸿蒙( Beta5.0)摄像头实践开发详解
驱动开发·华为·移动开发·harmonyos·鸿蒙·鸿蒙系统·openharmony
硬核科技8 小时前
变压器在电源中的核心作用
网络·单片机·嵌入式硬件·硬件工程·智能硬件·开关电源
CV金科9 小时前
蓝桥杯-STM32G431RBT6(UART解析字符串sscanf和解决串口BUG)
c语言·stm32·单片机·嵌入式硬件·mcu·算法·bug