Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
526fd10c
D
Docs
项目概览
OpenHarmony
/
Docs
接近 2 年 前同步成功
通知
159
Star
292
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
未验证
提交
526fd10c
编写于
12月 30, 2022
作者:
O
openharmony_ci
提交者:
Gitee
12月 30, 2022
浏览文件
操作
浏览文件
下载
差异文件
!12942 内核文档优化:内核启动与基础内核部分
Merge pull request !12942 from zhangdengyu/cherry-pick-1672121850
上级
89ae528e
00644491
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
230 addition
and
123 deletion
+230
-123
zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md
zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md
+48
-23
zh-cn/device-dev/kernel/kernel-small-basic-process-process.md
...n/device-dev/kernel/kernel-small-basic-process-process.md
+46
-15
zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md
...device-dev/kernel/kernel-small-basic-process-scheduler.md
+11
-7
zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md
zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md
+103
-59
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
+18
-17
zh-cn/device-dev/kernel/kernel-small-start-user.md
zh-cn/device-dev/kernel/kernel-small-start-user.md
+4
-2
未找到文件。
zh-cn/device-dev/kernel/kernel-small-basic-interrupt.md
浏览文件 @
526fd10c
...
@@ -3,16 +3,28 @@
...
@@ -3,16 +3,28 @@
## 基本概念
## 基本概念
中断是指出现需要时,CPU暂停执行当前程序,转而执行新程序的过程。即在程序运行过程中,出现了一个必须由CPU立即处理的事务。此时,CPU暂时中止当前程序的执行转而处理这个事务,这个过程就叫做中断。通过中断机制,可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,大大提高系统实时性以及执行效率。
中断是指出现需要时,CPU暂停执行当前程序,转而执行新程序的过程。即在程序运行过程中,出现了一个必须由CPU立即处理的事务,此时CPU暂时中止当前程序的执行转而处理这个事务,这个过程就叫做中断。通过中断机制,可以使CPU避免把大量时间耗费在等待、查询外设状态的操作上,大大提高系统实时性以及执行效率。
目前的中断支持有
+
中断初始化
+
中断创建
+
开/关中断
+
恢复中断
+
删除中断
异常处理是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,例如虚拟内存缺页异常、打印异常发生时函数的调用栈信息、CPU现场信息、任务的堆栈情况等。
异常处理是操作系统对运行期间发生的异常情况(芯片硬件异常)进行处理的一系列动作,例如虚拟内存缺页异常、打印异常发生时函数的调用栈信息、CPU现场信息、任务的堆栈情况等。
## 运行机制
## 运行机制
外设可以在没有CPU介入的情况下完成一定的工作,但某些情况下也需要CPU为其执行一定的工作。通过中断机制,在外设不需要CPU介入时,CPU可以执行其它任务,而当外设需要CPU时,产生一个中断信号,该信号连接至中断控制器。中断控制器是一方面接收其它外设中断引脚的输入,另一方面它会发出中断信号给CPU。可以通过对中断控制器编程来打开和关闭中断源、设置中断源的优先级和触发方式。常用的中断控制器有VIC(Vector Interrupt Controller)和GIC(General Interrupt Controller)。在ARM Cortex-A7中使用的中断控制器是GIC。CPU收到中断控制器发送的中断信号后,中断当前任务来响应中断请求。
外设可以在没有CPU介入的情况下完成一定的工作,但某些情况下也需要CPU为其执行一定的工作。通过中断机制,在外设不需要CPU介入时,CPU可以执行其它任务,而当外设需要CPU时,产生一个中断信号,该信号连接至中断控制器。
中断控制器一方面接收其它外设中断引脚的输入,另一方面会发出中断信号给CPU。可以通过对中断控制器编程来打开和关闭中断源、设置中断源的优先级和触发方式。常用的中断控制器有VIC(Vector Interrupt Controller)和GIC(General Interrupt Controller)。在ARM Cortex-A7中使用的中断控制器是GIC。
异常处理就是可以打断CPU正常运行流程的一些事情,如未定义指令异常、试图修改只读的数据异常、不对齐的地址访问异常等。当异常发生时,CPU暂停当前的程序,先处理异常事件,然后再继续执行被异常打断的程序。
CPU收到中断控制器发送的中断信号后,中断当前任务来响应中断请求。
异常指可以打断CPU正常运行流程的一些事情,如未定义指令异常、试图修改只读的数据异常、不对齐的地址访问异常等。当异常发生时,CPU暂停当前的程序,先处理异常事件,然后再继续执行被异常打断的程序。
以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。
以ARMv7-a架构为例,中断和异常处理的入口为中断向量表,中断向量表包含各个中断和异常处理的入口函数。
...
@@ -28,11 +40,27 @@
...
@@ -28,11 +40,27 @@
异常处理为内部机制,不对外提供接口,中断模块提供对外接口如下:
异常处理为内部机制,不对外提供接口,中断模块提供对外接口如下:
| 功能分类 | 接口描述 |
##### 创建删除中断
| -------- | -------- |
| 创建和删除中断 | -
LOS_HwiCreate:中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序
<br/>
-
LOS_HwiDelete:删除中断 |
| 接口名 | 接口描述 |
| 打开和关闭所有中断 | -
LOS_IntUnLock:打开当前处理器所有中断响应
<br/>
-
LOS_IntLock:关闭当前处理器所有中断响应
<br/>
-
LOS_IntRestore:恢复到使用LOS_IntLock关闭所有中断之前的状态 |
| :------------ | :----------------------------------------------------------- |
| 获取系统支持的最大中断数 | LOS_GetSystemHwiMaximum:获取系统支持的最大中断数 |
| LOS_HwiCreate | 中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序 |
| LOS_HwiDelete | 根据所提供的中断号删除中断 |
##### 开/关中断
| 接口名 | 接口描述 |
| -------------- | ------------------------------------------- |
| LOS_IntUnlock | 打开当前处理器所有中断响应 |
| LOS_IntLock | 关闭当前处理器所有中断响应 |
| LOS_IntRestore | 与LOS_IntLock配套使用,恢复到使用LOS_IntLock关闭所有中断之前的状态 |
##### 获取系统中断信息
| 接口名 | 接口描述 |
| ----------------------- | ------------------------ |
| LOS_GetSystemHwiMaximum | 获取系统支持的最大中断数 |
### 开发流程
### 开发流程
...
@@ -53,32 +81,30 @@
...
@@ -53,32 +81,30 @@
2.
删除中断。
2.
删除中断。
代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数:
代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI_NUM_TEST产生中断时,会调用中断处理函数(该示例代码的测试函数可以加在kernel/liteos_a/testsuites/kernel/src/osTest.c中的TestTaskEntry中进行测试):
```
c
```
#include "los_hwi.h"
#include "los_hwi.h"
/*中断处理函数*/
/*中断处理函数*/
STATIC
VOID
HwiUsrIrq
(
VOID
)
STATIC
VOID
HwiUsrIrq
(
VOID
)
{
{
printf("in the func HwiUsrIrq \n");
PRINK
(
"in the func HwiUsrIrq
\n
"
);
}
}
static
UINT32
Example_Interrupt
(
VOID
)
static
UINT32
Example_Interrupt
(
VOID
)
{
{
UINT32
ret
;
UINT32
ret
;
HWI_HANDLE_T hwiNum = 7;
HWI_HANDLE_T
hwiNum
=
7
;
// 7: 使用的中断号
HWI_PRIOR_T hwiPrio = 3;
HWI_PRIOR_T
hwiPrio
=
3
;
// 3: 中断优先级
HWI_MODE_T
mode
=
0
;
HWI_MODE_T
mode
=
0
;
HWI_ARG_T
arg
=
0
;
HWI_ARG_T
arg
=
0
;
/*创建中断*/
/*创建中断*/
ret
=
LOS_HwiCreate
(
hwiNum
,
hwiPrio
,
mode
,
(
HWI_PROC_FUNC
)
HwiUsrIrq
,
(
HwiIrqParam
*
)
arg
);
ret
=
LOS_HwiCreate
(
hwiNum
,
hwiPrio
,
mode
,
(
HWI_PROC_FUNC
)
HwiUsrIrq
,
(
HwiIrqParam
*
)
arg
);
if
(ret == LOS_OK)
{
if
(
ret
==
LOS_OK
)
{
printf
("Hwi create success!\n");
PRINK
(
"Hwi create success!
\n
"
);
}
else
{
}
else
{
printf
("Hwi create failed!\n");
PRINK
(
"Hwi create failed!
\n
"
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
...
@@ -86,11 +112,11 @@ static UINT32 Example_Interrupt(VOID)
...
@@ -86,11 +112,11 @@ static UINT32 Example_Interrupt(VOID)
LOS_TaskDelay
(
50
);
LOS_TaskDelay
(
50
);
/*删除中断*/
/*删除中断*/
ret = LOS_HwiDelete(hwiNum, (HwiIrqParam *)arg);
ret
=
LOS_HwiDelete
(
hwiNum
,
(
HwiIrqParam
*
)
arg
);
if
(ret == LOS_OK)
{
if
(
ret
==
LOS_OK
)
{
printf
("Hwi delete success!\n");
PRINK
(
"Hwi delete success!
\n
"
);
}
else
{
}
else
{
printf
("Hwi delete failed!\n");
PRINK
(
"Hwi delete failed!
\n
"
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
return
LOS_OK
;
return
LOS_OK
;
...
@@ -102,7 +128,6 @@ static UINT32 Example_Interrupt(VOID)
...
@@ -102,7 +128,6 @@ static UINT32 Example_Interrupt(VOID)
编译运行得到的结果为:
编译运行得到的结果为:
```
```
Hwi create success!
Hwi create success!
Hwi delete success!
Hwi delete success!
...
...
zh-cn/device-dev/kernel/kernel-small-basic-process-process.md
浏览文件 @
526fd10c
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
## 基本概念
## 基本概念
进程是系统资源管理的最小单元。OpenHarmony LiteOS-A
内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间
)。
进程是系统资源管理的最小单元。OpenHarmony LiteOS-A
内核提供的进程模块主要用于实现用户态进程的隔离,内核态被视为一个进程空间,不存在其它进程(KIdle除外,KIdle进程是系统提供的空闲进程,和KProcess共享一个进程空间。KProcess 是内核态进程的根进程,KIdle 是其子进程
)。
-
进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。
-
进程模块主要为用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。
...
@@ -36,10 +36,10 @@
...
@@ -36,10 +36,10 @@
**进程状态迁移说明:**
**进程状态迁移说明:**
-
Init→Ready:
-
Init→Ready:
进程创建或
fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程
插入调度队列,此时进程进入就绪状态。
进程创建或
fork 时,拿到对应进程控制块后进入 Init 状态,即进程初始化阶段,当该阶段完成后进程将被
插入调度队列,此时进程进入就绪状态。
-
Ready→Running:
-
Ready→Running:
进程创建后进入就绪态,发生进程切换时,就绪列表中
最高优先级
的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。
进程创建后进入就绪态,发生进程切换时,就绪列表中
优先级最高且获得时间片
的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存,但对外呈现的进程状态为运行态。
-
Running→Pending:
-
Running→Pending:
进程在最后一个线程转为阻塞态时, 进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。
进程在最后一个线程转为阻塞态时, 进程内所有的线程均处于阻塞态,此时进程同步进入阻塞态,然后发生进程切换。
...
@@ -54,7 +54,7 @@
...
@@ -54,7 +54,7 @@
进程由运行态转为就绪态的情况有以下两种:
进程由运行态转为就绪态的情况有以下两种:
1.
有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。
1.
有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。
2.
若进程的调度策略为
LOS_SCHED_RR
,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。
2.
若进程的调度策略为
LOS_SCHED_RR(时间片轮转)
,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。
-
Running→Zombies:
-
Running→Zombies:
当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。
当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。
...
@@ -78,16 +78,47 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,
...
@@ -78,16 +78,47 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,
### 接口说明
### 接口说明
**表1**
进程管理模块接口
##### 表1 进程及进程组
| 接口名 | 接口描述 |
| ------------------------- | ---------------------- |
| LOS_GetCurrProcessID | 获取当前进程的进程ID |
| LOS_GetProcessGroupID | 获取指定进程的进程组ID |
| LOS_GetCurrProcessGroupID | 获取当前进程的进程组ID |
##### 表2 用户及用户组
| 接口名 | 接口描述 |
| ----------------- | ---------------------------------------- |
| LOS_GetUserID | 获取当前进程的用户ID |
| LOS_GetGroupID | 获取当前进程的用户组ID |
| LOS_CheckInGroups | 检查指定用户组ID是否在当前进程的用户组内 |
##### 表3 进程调度控制
| 接口名 | 接口 |
| ----------------------- | -------------------------------------------- |
| LOS_GetProcessScheduler | 获取指定进程的调度策略 |
| LOS_SetProcessScheduler | 设置指定进程的调度参数,包括优先级和调度策略 |
| LOS_SetProcessPriority | 设置进程优先级 |
| LOS_GetProcessPriority | 获取进程优先级 |
##### 表4 系统进程信息获取
| 接口名 | 接口描述 |
| --------------------------- | -------------------------- |
| LOS_GetSystemProcessMaximum | 获取系统支持的最大进程数目 |
| LOS_GetUsedPIDList | 获得已使用的进程ID列表 |
##### 表5 进程创建与结束
| 接口名 | 接口描述 |
| ---------- | -------------------------- |
| LOS_Fork | 创建子进程 |
| LOS_Wait | 等待子进程结束并回收子进程 |
| LOS_Waitid | 等待相应ID的进程结束 |
| LOS_Exit | 退出进程 |
| 功能分类 | 接口描述 |
| -------- | -------- |
| 进程调度参数控制 | -
LOS_GetProcessScheduler:获取指定进程的调度策略
<br/>
-
LOS_SetProcessScheduler:设置指定进程的调度参数,包括优先级和调度策略 |
| 等待回收子进程 | LOS_Wait:等待子进程结束并回收子进程 |
| 进程组 | -
LOS_GetProcessGroupID:获取指定进程的进程组ID
<br/>
-
LOS_GetCurrProcessGroupID:获取当前进程的进程组ID |
| 获取进程ID | LOS_GetCurrProcessID:获取当前进程的进程ID |
| 用户及用户组 | -
LOS_GetUserID:获取当前进程的用户ID
<br/>
-
LOS_GetGroupID:获取当前进程的用户组ID
<br/>
-
LOS_CheckInGroups:检查指定用户组ID是否在当前进程的用户组内 |
| 系统支持的最大进程数 | LOS_GetSystemProcessMaximum:获取系统支持的最大进程数目 |
### 开发流程
### 开发流程
...
@@ -96,7 +127,7 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,
...
@@ -96,7 +127,7 @@ OpenHarmony 提供的进程模块主要用于实现用户态进程的隔离,
>  **说明:**
>  **说明:**
> - idle线程的数量跟随CPU核心数,每个CPU均有一个相应的idle线程。
> - idle线程的数量跟随CPU核心数,每个CPU均有一个相应的idle线程。
>
>
> - 不支持创建除KProcess和KIdle进程之外的其它内核态进程。
> - 不支持创建除KProcess和KIdle进程之外的其它内核态进程。
>
>
> - 用户态进程通过系统调用进入内核态后创建的线程属于KProcess, 不属于当前用户态进程。
> - 用户态进程通过系统调用进入内核态后创建的线程属于KProcess, 不属于当前用户态进程。
zh-cn/device-dev/kernel/kernel-small-basic-process-scheduler.md
浏览文件 @
526fd10c
...
@@ -3,18 +3,18 @@
...
@@ -3,18 +3,18 @@
## 基本概念
## 基本概念
OpenHarmony LiteOS-A内核
了高优先级优先+
同优先级时间片轮转的抢占式调度机制,系统从启动开始基于real time的时间轴向前运行,使得该调度算法具有很好的实时性。
OpenHarmony LiteOS-A内核
采用了高优先级优先 +
同优先级时间片轮转的抢占式调度机制,系统从启动开始基于real time的时间轴向前运行,使得该调度算法具有很好的实时性。
OpenHarmony 的调度算法将
tickless机制天然嵌入到调度算法中,一方面使得系统具有更低的功耗,另一方面也使得tick中断按需响应,减少无用的tick
中断响应,进一步提高系统的实时性。
OpenHarmony 的调度算法将
tickless 机制天然嵌入到调度算法中,一方面使得系统具有更低的功耗,另一方面也使得 tick 中断按需响应,减少无用的 tick
中断响应,进一步提高系统的实时性。
OpenHarmony 的进程调度策略支持
SCHED_RR,线程调度策略支持SCHED_RR和SCHED_FIFO
。
OpenHarmony 的进程调度策略支持
SCHED_RR(时间片轮转),线程调度策略支持 SCHED_RR 和 SCHED_FIFO(先进先出)
。
OpenHarmony 调度的最小单元为线程。
OpenHarmony 调度的最小单元为线程。
## 运行机制
## 运行机制
OpenHarmony 采用进程优先级队列
+
线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。
OpenHarmony 采用进程优先级队列
+
线程优先级队列的方式,进程优先级范围为0-31,共有32个进程优先级桶队列,每个桶队列对应一个线程优先级桶队列;线程优先级范围也为0-31,一个线程优先级桶队列也有32个优先级队列。
**图1**
调度优先级桶队列示意图
**图1**
调度优先级桶队列示意图
...
@@ -31,9 +31,13 @@ OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中
...
@@ -31,9 +31,13 @@ OpenHarmony 在系统启动内核初始化之后开始调度,运行过程中
### 接口说明
### 接口说明
| 功能分类 | 接口
**名称**
| 描述 |
| 接口
**名称**
| 描述 |
| -------- | -------- | -------- |
| -------- | -------- |
| 触发系统调度 | LOS_Schedule | 触发系统调度 |
| LOS_Schedule | 触发系统调度 |
| LOS_GetTaskScheduler | 获取指定任务的调度策略 |
| LOS_SetTaskScheduler | 设置指定任务的调度策略 |
| LOS_GetProcessScheduler | 获取指定进程的调度策略 |
| LOS_SetProcessScheduler | 设置指定进程的调度参数,包括优先级和调度策略 |
### 开发流程
### 开发流程
...
...
zh-cn/device-dev/kernel/kernel-small-basic-process-thread.md
浏览文件 @
526fd10c
...
@@ -52,7 +52,7 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0
...
@@ -52,7 +52,7 @@ OpenHarmony 内核的任务一共有32个优先级(0-31),最高优先级为0
有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,并加入就绪列表中。
有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪列表中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,并加入就绪列表中。
-
Running→Exit:
-
Running→Exit:
运行中的任务运行结束,任务状态由运行态变为退出态。若为设置了分离属性(
LOS_TASK_STATUS_DETACHED
)的任务,运行结束后将直接销毁。
运行中的任务运行结束,任务状态由运行态变为退出态。若为设置了分离属性(
由头文件 los_task.h 中的宏定义 LOS_TASK_STATUS_DETACHED 设置
)的任务,运行结束后将直接销毁。
## 运行机制
## 运行机制
...
@@ -67,16 +67,58 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起
...
@@ -67,16 +67,58 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起
### 接口说明
### 接口说明
| 功能分类 | 接口描述 |
##### 表1 任务的创建和删除
| -------- | -------- |
| 任务的创建和删除 | -
LOS_TaskCreate:创建任务,并使该任务进入Init状态,不执行任务调度
<br/>
-
LOS_TaskDelete:创建任务,并使该任务进入Ready状态,并调度
<br/>
-
LOS_TaskDelete:删除指定的任务 |
| 接口名 | 接口描述 |
| 任务状态控制 | -
LOS_TaskResume:恢复挂起的任务
<br/>
-
LOS_TaskSuspend:挂起指定的任务
<br/>
-
LOS_TaskJoin:挂起当前任务,等待指定任务运行结束并回收其任务控制块资源
<br/>
-
LOS_TaskDetach:修改任务的joinable属性为detach属性,detach属性的任务运行结束会自动回收任务控制块资源
<br/>
-
LOS_TaskDelay:任务延时等待
<br/>
-
LOS_TaskYield:显式放权,调整调用任务优先级的任务调度顺序 |
| ------------------ | ------------------------------------------------------------ |
| 任务调度的控制 | -
LOS_TaskLock:锁任务调度
<br/>
-
LOS_TaskUnlock:解锁任务调度 |
| LOS_TaskCreate | 创建任务,若所创建任务的优先级比当前的运行的任务优先级高且任务调度没有锁定,
<br/>
则该任务将被调度进入运行态 |
| 任务优先级的控制 | -
LOS_CurTaskPriSet:设置当前任务的优先级
<br/>
-
LOS_TaskPriSet:设置指定任务的优先级
<br/>
-
LOS_TaskPriGet:获取指定任务的优先级 |
| LOS_TaskCreateOnly | 创建任务并阻塞,任务恢复前不会将其加入就绪队列中 |
| 任务信息获取 | -
LOS_CurTaskIDGet:获取当前任务的ID
<br/>
-
LOS_TaskInfoGet:获取指定任务的信息 |
| LOS_TaskDelete | 删除指定的任务,回收其任务控制块和任务栈所消耗的资源 |
| 任务绑核操作 | -
LOS_TaskCpuAffiSet:绑定指定任务到指定CPU上运行,仅在多核下使用
<br/>
-
LOS_TaskCpuAffiGet:获取指定任务的绑核信息,仅在多核下使用 |
| 任务调度参数的控制 | -
LOS_GetTaskScheduler:获取指定任务的调度策略
<br/>
-
LOS_SetTaskScheduler:设置指定任务的调度参数,包括优先级和调度策略 |
##### 表2 任务的状态控制
| 系统支持的最大任务数 | LOS_GetSystemTaskMaximum |
| 接口名 | 接口描述 |
| --------------- | ------------------------------------------------------------ |
| LOS_TaskResume | 恢复挂起的任务 |
| LOS_TaskSuspend | 挂起指定的任务,该任务将从就绪任务队列中移除 |
| LOS_TaskJoin | 阻塞当前任务,等待指定任务运行结束并回收其资源 |
| LOS_TaskDetach | 修改任务的 joinable 属性为 detach 属性,detach 属性的任务运行结束会自动回收任务控制块资源 |
| LOS_TaskDelay | 延迟当前任务的执行,在延后指定的时间(tick数)后可以被调度 |
| LOS_TaskYield | 将当前任务从具有相同优先级的任务队列,移动到就绪任务队列的末尾 |
##### 表3 任务调度
| 接口名 | 接口描述 |
| -------------------- | ------------------------------------------------------------ |
| LOS_TaskLock | 锁定任务调度,阻止任务切换 |
| LOS_TaskUnlock | 解锁任务调度。通过该接口可以使任务锁数量减1,若任务多次加锁,那么
<br/>
任务调度在锁数量减为0时才会完全解锁 |
| LOS_GetTaskScheduler | 获取指定任务的调度策略 |
| LOS_SetTaskScheduler | 设置指定任务的调度参数,包括优先级和调度策略 |
| LOS_Schedule | 触发主动的任务调度 |
##### 表4 任务相关信息获取
| 接口名 | 接口描述 |
| ------------------------ | ------------------------ |
| LOS_CurTaskIDGet | 获取当前任务的ID |
| LOS_TaskInfoGet | 获取指定任务的信息 |
| LOS_GetSystemTaskMaximum | 获取系统支持的最大任务数 |
##### 表5 任务优先级
| 接口名 | 接口描述 |
| ----------------- | ------------------------------ |
| LOS_CurTaskPriSet | 设置当前正在运行的任务的优先级 |
| LOS_TaskPriSet | 设置指定任务的优先级 |
| LOS_TaskPriGet | 获取指定任务的优先级 |
##### 表6 任务绑核操作
| 接口名 | 接口描述 |
| ------------------ | ------------------------------------------- |
| LOS_TaskCpuAffiSet | 绑定指定任务到指定CPU上运行,仅在多核下使用 |
| LOS_TaskCpuAffiGet | 获取指定任务的绑核信息,仅在多核下使用 |
### 开发流程
### 开发流程
...
@@ -93,78 +135,79 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起
...
@@ -93,78 +135,79 @@ OpenHarmony 任务管理模块提供任务创建、任务延时、任务挂起
2.
任务参与调度运行,执行用户指定的业务代码。
2.
任务参与调度运行,执行用户指定的业务代码。
3.
任务执行结束,如果设置了
LOS_TASK_STATUS_DETACHED属性,则自动回收任务资源,如果任务设置了LOS_TASK_ATTR_JOINABLE属性,则需要调用LOS_TaskJoin回收任务资源,默认为LOS_TASK_STATUS_DETACHED
属性。
3.
任务执行结束,如果设置了
LOS_TASK_STATUS_DETACHED 属性,则自动回收任务资源,如果任务设置了 LOS_TASK_ATTR_JOINABLE 属性,则需要调用LOS_TaskJoin 回收任务资源,默认为 LOS_TASK_STATUS_DETACHED
属性。
>  **说明:**
>  **说明:**
> - 内核态具有最高权限,可以操作任意进程内的任务。
> - 内核态具有最高权限,可以操作任意进程内的任务。
>
>
> - 用户态进程通过系统调用进入内核态后创建的任务属于KProcess, 不属于当前用户态进程。
> - 用户态进程通过系统调用进入内核态后创建的任务属于KProcess, 不属于当前用户态进程。
### 编程实例
### 编程实例
代码实现如下:
代码实现如下
(该示例代码的测试函数可以加在 kernel /liteos_a/testsuites /kernel /src /osTest.c 中的 TestTaskEntry 中进行测试。)
:
```
```
c
UINT32
g_taskLoID
;
UINT32
g_taskLoID
;
UINT32 g_taskHiID;
UINT32
g_taskHiID
;
#define TSK_PRIOR_HI 4
#define TSK_PRIOR_HI 4
#define TSK_PRIOR_LO 5
#define TSK_PRIOR_LO 5
UINT32 ExampleTaskHi(VOID)
UINT32
ExampleTaskHi
(
VOID
)
{
{
UINT32
ret
;
UINT32
ret
;
PRINTK("Enter TaskHi Handler.\n");
PRINTK
(
"Enter TaskHi Handler.
\n
"
);
/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoID任务) */
/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中最高优先级的任务(g_taskLoID任务) */
ret
=
LOS_TaskDelay
(
2
);
ret
=
LOS_TaskDelay
(
2
);
if (ret != LOS_OK) {
if
(
ret
!=
LOS_OK
)
{
PRINTK
(
"Delay Task Failed.
\n
"
);
PRINTK
(
"Delay Task Failed.
\n
"
);
return LOS_NOK;
return
LOS_NOK
;
}
}
/* 2个Tick时间到了后,该任务恢复,继续执行 */
/* 2个Tick时间到了后,该任务恢复,继续执行 */
PRINTK("TaskHi LOS_TaskDelay Done.\n");
PRINTK
(
"TaskHi LOS_TaskDelay Done.
\n
"
);
/* 挂起自身任务 */
/* 挂起自身任务 */
ret = LOS_TaskSuspend(g_taskHiID);
ret
=
LOS_TaskSuspend
(
g_taskHiID
);
if
(
ret
!=
LOS_OK
)
{
if
(
ret
!=
LOS_OK
)
{
PRINTK("Suspend TaskHi Failed.\n");
PRINTK
(
"Suspend TaskHi Failed.
\n
"
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
PRINTK("TaskHi LOS_TaskResume Success.\n");
PRINTK
(
"TaskHi LOS_TaskResume Success.
\n
"
);
return
LOS_OK
;
return
LOS_OK
;
}
}
/* 低优先级任务入口函数 */
/* 低优先级任务入口函数 */
UINT32
ExampleTaskLo
(
VOID
)
UINT32
ExampleTaskLo
(
VOID
)
{
{
UINT32 ret;
UINT32
ret
;
PRINTK("Enter TaskLo Handler.\n");
PRINTK
(
"Enter TaskLo Handler.
\n
"
);
/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中就高优先级的任务(背景任务) */
/* 延时2个Tick,延时后该任务会挂起,执行剩余任务中就高优先级的任务(背景任务) */
ret = LOS_TaskDelay(2);
ret
=
LOS_TaskDelay
(
2
);
if (ret != LOS_OK) {
if
(
ret
!=
LOS_OK
)
{
PRINTK("Delay TaskLo Failed.\n");
PRINTK
(
"Delay TaskLo Failed.
\n
"
);
return LOS_NOK;
return
LOS_NOK
;
}
}
PRINTK
(
"TaskHi LOS_TaskSuspend Success.
\n
"
);
PRINTK
(
"TaskHi LOS_TaskSuspend Success.
\n
"
);
/* 恢复被挂起的任务g_taskHiID */
/* 恢复被挂起的任务g_taskHiID */
ret
=
LOS_TaskResume
(
g_taskHiID
);
ret
=
LOS_TaskResume
(
g_taskHiID
);
if
(
ret
!=
LOS_OK
)
{
if
(
ret
!=
LOS_OK
)
{
PRINTK
(
"Resume TaskHi Failed.
\n
"
);
PRINTK
(
"Resume TaskHi Failed.
\n
"
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
PRINTK("TaskHi LOS_TaskDelete Success.\n");
PRINTK
(
"TaskHi LOS_TaskDelete Success.
\n
"
);
return
LOS_OK
;
return
LOS_OK
;
}
}
/* 任务测试入口函数,在里面创建优先级不一样的两个任务 */
/* 任务测试入口函数,在里面创建优先级不一样的两个任务 */
UINT32 ExampleTaskCaseEntry(VOID)
UINT32
ExampleTaskCaseEntry
(
VOID
)
{
{
UINT32 ret;
UINT32
ret
;
TSK_INIT_PARAM_S
initParam
=
{
0
};
TSK_INIT_PARAM_S
initParam
=
{
0
};
/* 锁任务调度 */
/* 锁任务调度 */
LOS_TaskLock
();
LOS_TaskLock
();
PRINTK
(
"LOS_TaskLock() Success!
\n
"
);
PRINTK
(
"LOS_TaskLock() Success!
\n
"
);
/* 高优先级任务的初始化参数,其资源回收需要其他任务调用 LOS_TaskJoin */
initParam
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
ExampleTaskHi
;
initParam
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
ExampleTaskHi
;
initParam.usTaskPrio = TSK_PRIOR_HI;
initParam
.
usTaskPrio
=
TSK_PRIOR_HI
;
initParam
.
pcName
=
"HIGH_NAME"
;
initParam
.
pcName
=
"HIGH_NAME"
;
initParam
.
uwStackSize
=
LOS_TASK_MIN_STACK_SIZE
;
initParam
.
uwStackSize
=
LOS_TASK_MIN_STACK_SIZE
;
initParam
.
uwResved
=
LOS_TASK_ATTR_JOINABLE
;
initParam
.
uwResved
=
LOS_TASK_ATTR_JOINABLE
;
...
@@ -175,23 +218,24 @@ UINT32 ExampleTaskCaseEntry(VOID)
...
@@ -175,23 +218,24 @@ UINT32 ExampleTaskCaseEntry(VOID)
LOS_TaskUnlock
();
LOS_TaskUnlock
();
PRINTK
(
"ExampleTaskHi create Failed! ret=%d
\n
"
,
ret
);
PRINTK
(
"ExampleTaskHi create Failed! ret=%d
\n
"
,
ret
);
return
LOS_NOK
;
return
LOS_NOK
;
}
}
PRINTK
(
"ExampleTaskHi create Success!
\n
"
);
PRINTK
(
"ExampleTaskHi create Success!
\n
"
);
/* 低优先级任务的初始化参数,任务结束后会自行结束销毁 */
initParam
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
ExampleTaskLo
;
initParam
.
pfnTaskEntry
=
(
TSK_ENTRY_FUNC
)
ExampleTaskLo
;
initParam
.
usTaskPrio
=
TSK_PRIOR_LO
;
initParam
.
usTaskPrio
=
TSK_PRIOR_LO
;
initParam
.
pcName
=
"LOW_NAME"
;
initParam
.
pcName
=
"LOW_NAME"
;
initParam
.
uwStackSize
=
LOS_TASK_MIN_STACK_SIZE
;
initParam
.
uwStackSize
=
LOS_TASK_MIN_STACK_SIZE
;
initParam
.
uwResved
=
LOS_TASK_STATUS_DETACHED
;
initParam
.
uwResved
=
LOS_TASK_STATUS_DETACHED
;
/* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
/* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */
ret
=
LOS_TaskCreate
(
&
g_taskLoID
,
&
initParam
);
ret
=
LOS_TaskCreate
(
&
g_taskLoID
,
&
initParam
);
if (ret!= LOS_OK) {
if
(
ret
!=
LOS_OK
)
{
LOS_TaskUnlock();
LOS_TaskUnlock
();
PRINTK
(
"ExampleTaskLo create Failed!
\n
"
);
PRINTK
(
"ExampleTaskLo create Failed!
\n
"
);
return LOS_NOK;
return
LOS_NOK
;
}
}
PRINTK("ExampleTaskLo create Success!\n");
PRINTK
(
"ExampleTaskLo create Success!
\n
"
);
/* 解锁任务调度,此时会发生任务调度,执行就绪列表中最高优先级任务 */
/* 解锁任务调度,此时会发生任务调度,执行就绪列表中最高优先级任务 */
LOS_TaskUnlock
();
LOS_TaskUnlock
();
...
@@ -203,12 +247,12 @@ UINT32 ExampleTaskCaseEntry(VOID)
...
@@ -203,12 +247,12 @@ UINT32 ExampleTaskCaseEntry(VOID)
}
}
while
(
1
){};
while
(
1
){};
return
LOS_OK
;
return
LOS_OK
;
}
}
```
```
编译运行得到的结果为:
编译运行得到的结果为:
```
```
LOS_TaskLock() Success!
LOS_TaskLock() Success!
ExampleTaskHi create Success!
ExampleTaskHi create Success!
...
...
zh-cn/device-dev/kernel/kernel-small-start-kernel.md
浏览文件 @
526fd10c
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
## 内核启动流程
## 内核启动流程
内核启动流程包含汇编启动阶段和C语言启动阶段2部分,如图1所示。汇编启动阶段完成CPU初始设置,关闭dcache/icache,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等,其中如
上图
所示,OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,图中右边区域为启动框架中可接受外部模块注册启动的阶段,各个阶段的说明如下表1所示。
内核启动流程包含汇编启动阶段和C语言启动阶段2部分,如图1所示。汇编启动阶段完成CPU初始设置,关闭dcache/icache,使能FPU及neon,设置MMU建立虚实地址映射,设置系统栈,清理bss段,调用C语言main函数等。C语言启动阶段包含OsMain函数及开始调度等,其中如
图1
所示,OsMain函数用于内核基础初始化和架构、板级初始化等,其整体由内核启动框架主导初始化流程,图中右边区域为启动框架中可接受外部模块注册启动的阶段,各个阶段的说明如下表1所示。
**图1**
内核启动流程图
**图1**
内核启动流程图
...
@@ -12,24 +12,25 @@
...
@@ -12,24 +12,25 @@
**表1**
启动框架层级
**表1**
启动框架层级
| 层级 | 说明 |
| 层级 | 说明 |
| -------- | -------- |
| -------- | -------- |
| LOS_INIT_LEVEL_EARLIEST | 最早期初始化
<br/>
说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化
<br/>
例如:Trace模块 |
| LOS_INIT_LEVEL_EARLIEST | 最早期初始化
<br/>
说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化
<br/>
例如:Trace模块 |
| LOS_INIT_LEVEL_ARCH_EARLY | 架构早期初始化
<br/>
说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层 |
| LOS_INIT_LEVEL_ARCH_EARLY | 架构早期初始化
<br/>
说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层 |
| LOS_INIT_LEVEL_PLATFORM_EARLY | 平台早期初始化
<br/>
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层
<br/>
例如:uart模块 |
| LOS_INIT_LEVEL_PLATFORM_EARLY | 平台早期初始化
<br/>
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层
<br/>
例如:uart模块 |
| LOS_INIT_LEVEL_KMOD_PREVM | 内存初始化前的内核模块初始化
<br/>
说明:在内存初始化之前需要使能的模块初始化 |
| LOS_INIT_LEVEL_KMOD_PREVM | 内存初始化前的内核模块初始化
<br/>
说明:在内存初始化之前需要使能的模块初始化 |
| LOS_INIT_LEVEL_VM_COMPLETE | 基础内存就绪后的初始化
<br/>
说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化
<br/>
例如:共享内存功能 |
| LOS_INIT_LEVEL_VM_COMPLETE | 基础内存就绪后的初始化
<br/>
说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化
<br/>
例如:共享内存功能 |
| LOS_INIT_LEVEL_ARCH | 架构后期初始化
<br/>
说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化 |
| LOS_INIT_LEVEL_ARCH | 架构后期初始化
<br/>
说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化 |
| LOS_INIT_LEVEL_PLATFORM | 平台后期初始化
<br/>
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化
<br/>
例如:驱动内核抽象层初始化(mmc、mtd) |
| LOS_INIT_LEVEL_PLATFORM | 平台后期初始化
<br/>
说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化
<br/>
例如:驱动内核抽象层初始化(mmc、mtd) |
| LOS_INIT_LEVEL_KMOD_BASIC | 内核基础模块初始化
<br/>
说明:内核可拆卸的基础模块初始化
<br/>
例如:VFS初始化 |
| LOS_INIT_LEVEL_KMOD_BASIC | 内核基础模块初始化
<br/>
说明:内核可拆卸的基础模块初始化
<br/>
例如:VFS初始化 |
| LOS_INIT_LEVEL_KMOD_EXTENDED | 内核扩展模块初始化
<br/>
说明:内核可拆卸的扩展模块初始化
<br/>
例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化 |
| LOS_INIT_LEVEL_KMOD_EXTENDED | 内核扩展模块初始化
<br/>
说明:内核可拆卸的扩展模块初始化
<br/>
例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化 |
| LOS_INIT_LEVEL_KMOD_TASK | 内核任务创建
<br/>
说明:进行内核任务的创建(内核任务,软件定时器任务)
<br/>
例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建 |
| LOS_INIT_LEVEL_KMOD_TASK | 内核任务创建
<br/>
说明:进行内核任务的创建(内核任务,软件定时器任务)
<br/>
例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建 |
| LOS_INIT_LEVEL_FINISH | 内核初始化完成 |
## 编程样例
## 编程样例
**实例描述**
**实例描述**
新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。
新增一个内核模块,需要在内核初始化时进行该模块的初始化,则通过内核启动框架将该模块的初始化函数注册进内核启动流程中。
...
@@ -37,8 +38,8 @@
...
@@ -37,8 +38,8 @@
**示例代码**
**示例代码**
```
```
c
/* 内核启动框架头文件 */
/* 内核启动框架头文件 */
#include "los_init.h"
#include "los_init.h"
......
......
...
@@ -58,7 +59,7 @@ LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
...
@@ -58,7 +59,7 @@ LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
**结果验证**
**结果验证**
```
```
main core booting up...
main core booting up...
OsSampleModInit SUCCESS!
OsSampleModInit SUCCESS!
...
@@ -73,5 +74,5 @@ cpu 0 entering scheduler
...
@@ -73,5 +74,5 @@ cpu 0 entering scheduler
>  **说明:**
>  **说明:**
> 启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。
> 启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。
>
>
> 可通过查看系统编译生成文件OHOS_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。
> 可通过查看系统编译生成文件OHOS_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。
zh-cn/device-dev/kernel/kernel-small-start-user.md
浏览文件 @
526fd10c
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
使用链接脚本将如下init启动代码放置到系统镜像指定位置。
使用链接脚本将如下init启动代码放置到系统镜像指定位置。
```
```
c
#define LITE_USER_SEC_ENTRY __attribute__((section(".user.entry")))
#define LITE_USER_SEC_ENTRY __attribute__((section(".user.entry")))
LITE_USER_SEC_ENTRY
VOID
OsUserInit
(
VOID
*
args
)
LITE_USER_SEC_ENTRY
VOID
OsUserInit
(
VOID
*
args
)
{
{
...
@@ -27,6 +27,8 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
...
@@ -27,6 +27,8 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
}
}
```
```
> 上述启动代码在 kernel/liteos_a/kernel/user/src/los_user_init.c 中,g_initPath 根据启动设置的不同,其值为 /dev/shm/init 或 /bin/init。
系统启动阶段,OsUserInitProcess启动init进程。具体过程如下:
系统启动阶段,OsUserInitProcess启动init进程。具体过程如下:
1.
由内核OsLoadUserInit加载上述代码。
1.
由内核OsLoadUserInit加载上述代码。
...
@@ -48,7 +50,7 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
...
@@ -48,7 +50,7 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
用户态程序启动有如下常见方式:
用户态程序启动有如下常见方式:
-
shell命令启动进程。
-
shell命令启动进程。
```
```
OHOS $ exec helloworld
OHOS $ exec helloworld
OHOS $ ./helloworld
OHOS $ ./helloworld
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录