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

本文开始继续分析OpenHarmony LiteOS-A内核的源代码,接下来会分析进程和任务管理模块。本文中所涉及的源码,以OpenHarmony LiteOS-A内核为例,均可以在开源站点 https://gitee.com/openharmony/kernel_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到子进程,子进程实际运行时通过写时复制机制将父进程的内容按需复制到子进程的虚拟内存空间。进程只是资源管理单元,实际运行是由进程内的各个线程完成的,不同进程内的线程相互切换时会进行进程空间的切换。

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_ForkFork进程
进程组LOS_GetProcessGroupID获取指定进程的进程组ID
LOS_GetCurrProcessGroupID获取当前进程的进程组ID
获取进程IDLOS_GetCurrProcessID获取当前进程的进程ID
LOS_GetUsedPIDList获取已用的进程ID列表,输出到进程ID数组
用户及用户组LOS_GetUserID获取当前进程的用户ID
LOS_GetGroupID获取当前进程的用户组ID
LOS_CheckInGroups检查指定用户组ID是否在当前进程的用户组内
系统支持的最大进程数LOS_GetSystemProcessMaximum获取系统支持的最大进程数目
文件描述符表LOS_GetFdTable根据进程ID获取文件描述符表

完整的接口声明如下:

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信息,信号信息,虚拟地址框架,文件,安全能力等。涉及具体代码时,再深入分析这些结构体成员。

    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中还定义了内联函数等。下述几个函数用于判断进程是否未使用,是否未激活状态,是否死亡进程,是否初始化,是否用户态进程等。

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

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

/*
 * 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 */
}

小结

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

如果大家想更加深入的学习 OpenHarmony 开发的内容,不妨可以参考以下相关学习文档进行学习,助你快速提升自己:

OpenHarmony 开发环境搭建:https://qr18.cn/CgxrRy

《OpenHarmony源码解析》:https://qr18.cn/CgxrRy

  • 搭建开发环境
  • Windows 开发环境的搭建
  • Ubuntu 开发环境搭建
  • Linux 与 Windows 之间的文件共享
  • ……

系统架构分析:https://qr18.cn/CgxrRy

  • 构建子系统
  • 启动流程
  • 子系统
  • 分布式任务调度子系统
  • 分布式通信子系统
  • 驱动子系统
  • ……

OpenHarmony 设备开发学习手册:https://qr18.cn/CgxrRy

在这里插入图片描述

OpenHarmony面试题(内含参考答案):https://qr18.cn/CgxrRy

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:https://qr21.cn/FV7h05

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/706716.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何翻译和本地化游戏?翻译访谈

如何翻译和本地化游戏&#xff1f;这个过程的技术细节有哪些&#xff1f;游戏翻译不同于电影翻译。Logrus IT游戏本地化部门负责人阿列克谢费奥多罗夫&#xff08;Alexey Fedorov&#xff09;在接受RUDN语言学系外语系教授和研究人员的采访时谈到了这一点&#xff0c;他是由尤利…

堆的应用——TOP-K问题

堆的应用——TOP-K问题 TOP-K 问题解决方法一、排序后选择二、简单数组维护三、使用堆优化简单数组方案 TOP-K 问题实例的堆代码参考(环境为VS2022的C语言)生成 1 千万个整数生成后检查文件建小堆处理问题验证正确性完整代码&#xff1a; TOP-K 问题 即求相同数据中前K个最大的…

【讯为Linux驱动开发】6.自旋锁spinlock

【自旋锁】 线程A获取自旋锁后&#xff0c;B假如想获取自旋锁则只能原地等待&#xff0c;仍占用CPU&#xff0c;不会休眠&#xff0c;直到获取自旋锁为止。 【函数】 DEFINE SINLOCK(spinlock t lock) 定义并初始化一个变量int spin lock init(spinlock t*lock) 初始化自…

设计通用灵活的LabVIEW自动测试系统

为了在不同客户案例中灵活使用不同设备&#xff08;如采集卡、Modbus模块&#xff09;且保持功能一致的LabVIEW自动测试系统&#xff0c;需要采用模块化的软件架构、配置文件管理、标准化接口和良好的升级维护策略。本文从软件架构、模块化设计、配置管理、升级维护、代码管理和…

docker-compose启动oracle11、并使用navicat进行连接

一、docker-compose.yml version: 3.9 services:oracle:image: registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11grestart: alwaysprivileged: truecontainer_name: oracle11gvolumes:- ./data:/u01/app/oracleports:- 1521:1521network_mode: "host"logging:d…

安卓/iOS/Linux系统影音边下边播P2P传输解决方案

在当今的数字时代&#xff0c;IPTV 影音行业正经历着快速的发展和变革&#xff0c;但影音行业的流量带宽成本一直很高&#xff0c;有没有什么办法既能保证现有的用户观看体验&#xff0c;又能很好降低流量带宽成本呢? P2P技术可能是一个很好的选择&#xff0c;它不仅仅可以提…

计算机组成原理(六)

0x12345678和12345678H都是指同一个十六进制,也就是12345678&#xff0c;不过是不同的编程语言的写法而已 具体来说&#xff0c;如果有 n 根地址线&#xff0c;计算机可以寻址的内存空间大小是 2^n 字节。 24根地址线&#xff1a; 如果一个系统有24根地址线&#xff0c;意味着它…

【日记】第一次养植物,没什么经验……(781 字)

正文 前两天梦见灵送的几盆植物全都死掉了。梦里好伤心。醒来与她说这件事&#xff0c;她宽慰我说&#xff0c;梦都是反着的&#xff0c;肯定能活得很好的。于是忽然记起昨天给植物换水时&#xff0c;文竹的根居然从花盆底部伸吊了出来&#xff0c;以前都没有这种情况来着&…

你知道古代青铜器的原色是什么吗?

在中国悠久的历史中&#xff0c;青铜器作为中华文明的瑰宝&#xff0c;一直以其独特的艺术魅力和深厚的文化内涵吸引着世人的目光。然而&#xff0c;对于大多数人来说&#xff0c;青铜器的形象往往与电视剧中的描绘有所出入。那些在剧中常见的青绿色青铜器&#xff0c;让许多观…

Kafka 负载均衡挑战及解决思路

本文转载自 Agoda Engineering&#xff0c;介绍了在实际应用中&#xff0c;如何应对 Kafka 负载均衡所遇到的各种挑战&#xff0c;并提出相应的解决思路。本文简要阐述了 Kafka 的并行性机制、常用的分区策略以及在实际操作中遇到的异构硬件、不均匀工作负载等问题。通过深入分…

使用Arthas查看方法的参数信息情况

使用Arthas查看方法的参数信息情况 前言 最近在排查一个bug&#xff0c;需要看看一个接口方法的传参&#xff0c;但是方法里并没有打印传参&#xff0c;而且还是生产环境&#xff0c;更新包也麻烦&#xff0c;所以&#xff0c;准备安装一下Arthas&#xff0c;通过Arthas可以做…

windows 11中如何设置默认为英文输入法

由于工作需要&#xff0c;我一直在windows7下使用VB6&#xff0c;以前尝试着使用新的系统&#xff0c;但都无法正常安装vb&#xff0c;最近几天由于系统一次作死操作&#xff0c;逼着我安装了win11&#xff0c;并且在其上正常安装了vb6&#xff0c;本想着十分高兴&#xff0c;终…

Ascend C 2.0新特性详解,支撑大模型融合算子高效开发

近日&#xff0c;昇腾算子编程语言Ascend C发布2.0版本&#xff0c;新增支持通算融合MC特性&#xff0c;使能大模型场景下通信和计算并行&#xff0c;提高整网运行性能&#xff1b;提供更丰富的API覆盖当前主流的融合算子开发场景&#xff0c;提升开发效率&#xff1b;同时通过…

大语言模型 (LLM) 红队测试:提前解决模型漏洞

大型语言模型 (LLM) 的兴起具有变革性&#xff0c;以其在自然语言处理和生成方面具有与人类相似的卓越能力&#xff0c;展现出巨大的潜力。然而&#xff0c;LLM 也被发现存在偏见、提供错误信息或幻觉、生成有害内容&#xff0c;甚至进行欺骗行为的情况。一些备受关注的事件包括…

clipboard.js(web页面实现点击复制)

文章目录 codeshow 一个很简单的需求&#xff0c;一个单页面需要一个点击复制的功能 后来在线上找到一个clipboard.js可以实现&#xff0c;这里只用到了最基础的用法&#xff0c;页面样式布局基于bootstrap5.2.3 code <div class"d-flex align-items-center justify-co…

字符设备驱动

目录 demo.c test.c led.h makefile 实验效果 demo.c #include <linux/init.h> #include <linux/module.h> #include <linux/fs.h> #include <linux/uaccess.h> #include <linux/io.h> #include "myled.h" //内核buf char kbuf[…

UITableView之cell复用

关于cell复用的必要性 cellForRowAtIndexPath会随着屏幕滚动而调用&#xff0c;每次出现新行时因为行号变化&#xff0c;就会被调用。 底层原理&#xff1a;当前单元格滚出屏幕时cell销毁&#xff0c;当前单元格又滚回来时cell创建。短时间内频繁创建和销毁cell会影响系统性能…

MySQL 触发器(实验报告)

一、实验名称&#xff1a; 触发器 二、实验日期&#xff1a; 2024 年 6月 8日 三、实验目的&#xff1a; 掌握MySQL触发器的创建及调用&#xff1b; 四、实验用的仪器和材料&#xff1a; 硬件&#xff1a;PC电脑一台&#xff1b; 配置&#xff1a;内存&#xff0c;…

React Native将 ipad 端软件设置为横屏显示后关闭 Modal 弹窗报错

问题&#xff1a; 将 ipad 端软件设置为横屏显示后&#xff0c;关闭 Modal 弹窗报错。 Modal was presented with 0x2 orientations mask but the application only supports 0x18.Add more interface orientations to your apps Info.plist to fix this.NOTE: This will cras…

幸狐RV1106开发板烧录Ubuntu系统与配置SDK,RV1106 LuckFox Pico Max——最新的操作

资料&#xff1a;上手教程 | LUCKFOX WIKI 以及SDK内的文档资料 开发板型号&#xff1a;RV1106 LuckFox Pico Max 烧录系统&#xff1a; Ubuntu 虚拟机系统&#xff1a;Ubuntu 20.04&&Ubuntu22.04 PC系统&#xff1a;win11 占用空间&#xff1a;大概15G 本文主要记…