前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >OpenHarmony 轻内核A核源码分析系列七 进程管理 (1)

OpenHarmony 轻内核A核源码分析系列七 进程管理 (1)

原创
作者头像
小帅聊鸿蒙
发布2025-06-06 16:04:16
发布2025-06-06 16:04:16
1320
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

本文开始继续分析OpenHarmony LiteOS-A内核的源代码,接下来会分析进程和任务管理模块。本文中所涉及的源码,以OpenHarmony LiteOS-A内核为例。如果涉及开发板,则默认以hispark_taurus为例。

本文先熟悉下进程管理的概念、运行机制和编程接口。

1、LiteOS-A内核进程基本概念

进程是系统资源管理的最小单元。OpenHarmony LiteOS-A内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间)。

1.1 LiteOS-A内核进程特征

LiteOS-A内核进程有如下特征:

  • 进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。
  • 进程采用抢占式调度机制,采用高优先级优先+同优先级时间片轮转的调度算法。
  • 进程一共有32个优先级(0-31),用户进程可配置的优先级有22个(10-31),最高优先级为10,最低优先级为31。
  • 高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。
  • 每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。
  • 用户态根进程init由内核态创建,其它用户态子进程均由init进程fork而来。

1.2 LiteOS-A内核进程状态

LiteOS-A内核进程状态包含初始化态、就绪态、运行态、阻塞态、僵死态等几种状态。

  • 初始化(Init):进程正在被创建。
  • 就绪(Ready):进程在就绪列表中,等待CPU调度。
  • 运行(Running):进程正在运行。

阻塞(Pending):进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。

  • 僵尸(Zombies):进程运行结束,等待父进程回收其控制块资源。

各个状态迁移示意图如下所示,图片来自openharmony docs文档仓:

进程状态迁移说明如下:

  • 1、Init→Ready: 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。
  • 2、Ready→Running: 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。
  • 3、Running→Pending: 进程在最后一个线程转为阻塞态时, 进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。
  • 4、Pending→Ready: 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。
  • 5、Ready→Pending: 进程内的最后一个就绪态线程转为阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。
  • 6、Running→Ready: 进程由运行态转为就绪态的情况有以下两种:
    • 6.1 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。
    • 6.2 若进程的调度策略为LOS_SCHED_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。
  • 7、Running→Zombies: 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。

2、LiteOS-A内核进程运行机制

OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,支持用户态进程的创建、退出、资源回收、设置/获取调度参数、获取进程ID、设置/获取进程组ID等功能。用户态进程通过fork父进程而来,fork进程时会将父进程的进程虚拟内存空间clone到子进程,子进程实际运行时通过写时复制机制将父进程的内容按需复制到子进程的虚拟内存空间。进程只是资源管理单元,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。

DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
代码语言:erlang
复制
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

3、LiteOS-A内核进程模块接口

3.1 LiteOS-A内核进程模块对外接口

进程模块对外接口文件kernel\include\los_process.h定义的接口,如下表所示。

功能分类

接口名称

描述

进程调度参数控制

LOS_GetProcessScheduler

获取指定进程的调度策略

LOS_SetProcessScheduler

设置指定进程的调度参数,包括优先级和调度策略

LOS_GetProcessPriority

获取指定进程的优先级

LOS_SetProcessPriority

设置指定进程的优先级

进程操作

LOS_Wait

等待子进程结束并回收子进程

LOS_Waitid

等待子进程结束并回收子进程

LOS_Exit

退出进程

LOS_Fork

Fork进程

进程组

LOS_GetProcessGroupID

获取指定进程的进程组ID

LOS_GetCurrProcessGroupID

获取当前进程的进程组ID

获取进程ID

LOS_GetCurrProcessID

获取当前进程的进程ID

LOS_GetUsedPIDList

获取已用的进程ID列表,输出到进程ID数组

用户及用户组

LOS_GetUserID

获取当前进程的用户ID

LOS_GetGroupID

获取当前进程的用户组ID

LOS_CheckInGroups

检查指定用户组ID是否在当前进程的用户组内

系统支持的最大进程数

LOS_GetSystemProcessMaximum

获取系统支持的最大进程数目

文件描述符表

LOS_GetFdTable

根据进程ID获取文件描述符表

完整的接口声明如下:

代码语言:shell
复制
extern INT32 LOS_Fork(UINT32 flags, const CHAR *name, const TSK_ENTRY_FUNC entry, UINT32 stackSize);

extern INT32 LOS_SetProcessPriority(INT32 pid, UINT16 prio);

extern INT32 LOS_GetProcessPriority(INT32 pid);

extern INT32 LOS_GetProcessScheduler(INT32 pid);

extern INT32 LOS_SetProcessScheduler(INT32 pid, UINT16 policy, UINT16 prio);

extern UINT32 LOS_GetCurrProcessID(VOID);

extern INT32 LOS_Wait(INT32 pid, USER INT32 *status, UINT32 options, VOID *rusage);

extern INT32 LOS_Waitid(INT32 pid, USER siginfo_t *info, UINT32 options, VOID *rusage);

extern INT32 LOS_GetCurrProcessGroupID(VOID);

extern INT32 LOS_GetProcessGroupID(UINT32 pid);

extern VOID LOS_Exit(INT32 status);

extern UINT32 LOS_GetSystemProcessMaximum(VOID);

#ifdef LOSCFG_SECURITY_CAPABILITY
extern BOOL LOS_CheckInGroups(UINT32 gid);
#endif
extern INT32 LOS_GetUserID(VOID);
extern INT32 LOS_GetGroupID(VOID);

extern INT32 LOS_GetUsedPIDList(UINT32 *pidList, INT32 pidMaxNum);

#ifdef LOSCFG_FS_VFS
struct fd_table_s *LOS_GetFdTable(UINT32 pid);
#endif

3.2 LiteOS-A内核进程模块结构体

私有头文件kernel\base\include\los_process_pri.h中定义了宏、结构体等。进程组、进程控制块结构体如下。对于进程组,如⑴所示,进程组的编号等于创建该进程组的进程的进程编号。每个进程组维护一个链表挂载本组的非僵尸态进程,还维护一个链表挂载本组的僵尸态进程。所有的进程都通过链表节点groupList挂载到全局进程组链表上,可以方便管理进程组。

进程控制块结构体比较复杂,⑵-⑶维护进程的名称、ID编号、状态、模式、退出状态等等,⑷-⑸维护各种链表,进程组信息,线程数量等。接下来,维护多核时的CPU信息,信号信息,虚拟地址框架,文件,安全能力等。涉及具体代码时,再深入分析这些结构体成员。

代码语言:shell
复制
    typedef struct {
⑴      UINT32      groupID;         /**< Process group ID is the PID of the process that created the group */
        LOS_DL_LIST processList;     /**< List of processes under this process group */
        LOS_DL_LIST exitProcessList; /**< List of closed processes (zombie processes) under this group */
        LOS_DL_LIST groupList;       /**< Process group list */
    } ProcessGroup;

    typedef struct ProcessCB {
⑵      CHAR                 processName[OS_PCB_NAME_LEN]; /**< Process name */
        UINT32               processID;                    /**< Process ID */
        UINT16               processStatus;                /**< [15:4] Process Status; [3:0] The number of threads currently
                                                                running in the process */
        UINT16               consoleID;                    /**< The console id of task belongs  */
        UINT16               processMode;                  /**< Kernel Mode:0; User Mode:1; */
        UINT32               parentProcessID;              /**< Parent process ID */
⑶      UINT32               exitCode;                     /**< Process exit status */
⑷      LOS_DL_LIST          pendList;                     /**< Block list to which the process belongs */
        LOS_DL_LIST          childrenList;                 /**< Children process list */
        LOS_DL_LIST          exitChildList;                /**< Exit children process list */
        LOS_DL_LIST          siblingList;                  /**< Linkage in parent's children list */
        ProcessGroup         *group;                       /**< Process group to which a process belongs */
        LOS_DL_LIST          subordinateGroupList;         /**< Linkage in group list */
        UINT32               threadGroupID;                /**< Which thread group , is the main thread ID of the process */
        LOS_DL_LIST          threadSiblingList;            /**< List of threads under this process */
        volatile UINT32      threadNumber; /**< Number of threads alive under this process */
        UINT32               threadCount;  /**< Total number of threads created under this process */
⑸      LOS_DL_LIST          waitList;     /**< The process holds the waitLits to support wait/waitpid */
    #ifdef LOSCFG_KERNEL_SMP
        UINT32               timerCpu;     /**< CPU core number of this task is delayed or pended */
    #endif
        UINTPTR              sigHandler;   /**< Signal handler */
        sigset_t             sigShare;     /**< Signal share bit */
    #ifdef LOSCFG_KERNEL_LITEIPC
        ProcIpcInfo          *ipcInfo;      /**< Memory pool for lite ipc */
    #endif
    #ifdef LOSCFG_KERNEL_VM
        LosVmSpace           *vmSpace;     /**< VMM space for processes */
    #endif
    #ifdef LOSCFG_FS_VFS
        struct files_struct  *files;       /**< Files held by the process */
    #endif
        timer_t              timerID;      /**< ITimer */

    #ifdef LOSCFG_SECURITY_CAPABILITY
        User                *user;
        UINT32              capability;
    #endif
    #ifdef LOSCFG_SECURITY_VID
        TimerIdMap           timerIdMap;
    #endif
    #ifdef LOSCFG_DRIVERS_TZDRIVER
        struct Vnode        *execVnode;   /**< Exec bin of the process */
    #endif
        mode_t               umask;
    #ifdef LOSCFG_KERNEL_CPUP
        OsCpupBase           *processCpup; /**< Process cpu usage */
    #endif
        struct rlimit        *resourceLimit;
    } LosProcessCB;

3.3 LiteOS-A内核进程模块内联函数

私有头文件kernel\base\include\los_process_pri.h中还定义了内联函数等。下述几个函数用于判断进程是否未使用,是否未激活状态,是否死亡进程,是否初始化,是否用户态进程等。

代码语言:shell
复制
STATIC INLINE BOOL OsProcessIsUnused(const LosProcessCB *processCB)
{
    return ((processCB->processStatus & OS_PROCESS_FLAG_UNUSED) != 0);
}

STATIC INLINE BOOL OsProcessIsInactive(const LosProcessCB *processCB)
{
    return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_INACTIVE)) != 0);
}

STATIC INLINE BOOL OsProcessIsDead(const LosProcessCB *processCB)
{
    return ((processCB->processStatus & (OS_PROCESS_FLAG_UNUSED | OS_PROCESS_STATUS_ZOMBIES)) != 0);
}

STATIC INLINE BOOL OsProcessIsInit(const LosProcessCB *processCB)
{
    return (processCB->processStatus & OS_PROCESS_STATUS_INIT);
}
STATIC INLINE BOOL OsProcessIsUserMode(const LosProcessCB *processCB)
{
    return (processCB->processMode == OS_USER_MODE);
}
DD一下:欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。
代码语言:erlang
复制
`欢迎大家关注工粽号<程序猿百晓生>,可以了解到以下知识点。`
1.OpenHarmony开发基础
2.OpenHarmony北向开发环境搭建
3.鸿蒙南向开发环境的搭建
4.鸿蒙生态应用开发白皮书V2.0 & V3.0
5.鸿蒙开发面试真题(含参考答案) 
6.TypeScript入门学习手册
7.OpenHarmony 经典面试题(含参考答案)
8.OpenHarmony设备开发入门【最新版】
9.沉浸式剖析OpenHarmony源代码
10.系统定制指南
11.【OpenHarmony】Uboot 驱动加载流程
12.OpenHarmony构建系统--GN与子系统、部件、模块详解
13.ohos开机init启动流程
14.鸿蒙版性能优化指南
.......

下述几个函数对指定进程设置不同的退出代码,coredump、signal等等。

代码语言:shell
复制
/*
 * Process exit code
 * 31    15           8           7        0
 * |     | exit code  | core dump | signal |
 */
#define OS_PRO_EXIT_OK 0
STATIC INLINE VOID OsProcessExitCodeCoreDumpSet(LosProcessCB *processCB)
{
    processCB->exitCode |= 0x80U;
}

STATIC INLINE VOID OsProcessExitCodeSignalSet(LosProcessCB *processCB, UINT32 signal)
{
    processCB->exitCode |= signal & 0x7FU;
}

STATIC INLINE VOID OsProcessExitCodeSignalClear(LosProcessCB *processCB)
{
    processCB->exitCode &= (~0x7FU);
}

STATIC INLINE BOOL OsProcessExitCodeSignalIsSet(LosProcessCB *processCB)
{
    return (processCB->exitCode) & 0x7FU;
}

STATIC INLINE VOID OsProcessExitCodeSet(LosProcessCB *processCB, UINT32 code)
{
    processCB->exitCode |= ((code & 0x000000FFU) << 8U) & 0x0000FF00U; /* 8: Move 8 bits to the left, exitCode */
}

小结

本文介绍了进程管理的概念、运行机制和编程接口。

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、LiteOS-A内核进程基本概念
    • 1.1 LiteOS-A内核进程特征
    • 1.2 LiteOS-A内核进程状态
  • 2、LiteOS-A内核进程运行机制
  • 3、LiteOS-A内核进程模块接口
    • 3.1 LiteOS-A内核进程模块对外接口
    • 3.2 LiteOS-A内核进程模块结构体
    • 3.3 LiteOS-A内核进程模块内联函数
  • 小结
    • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档