未验证 提交 ab654d23 编写于 作者: O openharmony_ci 提交者: Gitee

!14215 [翻译完成】#I6863G

Merge pull request !14215 from Annie_wang/PR12942
# Interrupt and Exception Handling # Interrupt and Exception Handling
## Basic Concepts<a name="section439816296117"></a> ## Basic Concepts
An interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention. An interrupt alerts the processor of a high-priority condition requiring interruption of the code being executed by the processor. In this way, the CPU does not need to spend a lot of time in waiting and querying the peripheral status, which effectively improves the real-time performance and execution efficiency of the system. An interrupt is a signal to the processor emitted by hardware or software indicating an event that needs immediate attention. An interrupt alerts the processor of a high-priority condition requiring interruption of the code being executed by the processor. In this way, the CPU does not need to spend a lot of time in waiting and querying the peripheral status, which effectively improves the real-time performance and execution efficiency of the system.
Exception handling involves a series of actions taken by the OS to respond to exceptions \(chip hardware faults\) that occurred during the OS running, for example, printing the call stack information of the current function, CPU information, and call stack information of tasks when the virtual memory page is missing. OpenHarmony supports the following interrupt operations:
## Working Principles<a name="section2792838318"></a> + Initializing an interrupt.
+ Creating an interrupt.
+ Enabling or disabling interrupts.
+ Restoring the system status before interrupts are disabled.
+ Deleting an interrupt.
Peripherals can complete certain work without the intervention of the CPU. In some cases, however, the CPU needs to perform certain work for peripherals. With the interrupt mechanism, the CPU responds to the interrupt request from a peripheral only when required, and execute other tasks when the peripherals do not require the CPU. The interrupt controller receives the input of other peripheral interrupt pins and sends interrupt signals to the CPU. You can enable or disable the interrupt source and set the priority and trigger mode of the interrupt source by programming the interrupt controller. Common interrupt controllers include vector interrupt controllers \(VICs\) and general interrupt controllers \(GICs\). The ARM Cortex-A7 uses GICs. After receiving an interrupt signal sent by the interrupt controller, the CPU interrupts the current task to respond to the interrupt request. Exception handling involves a series of actions taken by the OS to respond to exceptions (chip hardware faults) that occurred during the OS running, for example, printing the call stack information of the current function, CPU information, and call stack information of tasks when the virtual memory page is missing.
Exception handling interrupts the normal running process of the CPU to handle exceptions, such as, undefined instructions, an attempt to modify read-only data, and unaligned address access. When an exception occurs, the CPU suspends the current program, handles the exception, and then continues to execute the program interrupted by the exception.
## Working Principles
Peripherals can complete certain work without the intervention of the CPU. In some cases, however, the CPU needs to perform certain work for peripherals. With the interrupt mechanism, the CPU responds to the interrupt request from a peripheral only when required, and execute other tasks when the peripherals do not require the CPU.
The interrupt controller receives the input from the interrupt pins of other peripherals and sends interrupt signals to the CPU. You can enable or disable the interrupt source and set the priority and trigger mode of the interrupt source by programming the interrupt controller. Common interrupt controllers include vector interrupt controllers (VICs) and general interrupt controllers (GICs). The ARM Cortex-A7 uses GICs.
After receiving an interrupt signal sent by the interrupt controller, the CPU interrupts the current task to respond to the interrupt request.
An exception interrupts the normal running process of the CPU to handle exceptions, such as, undefined instructions, an attempt to modify read-only data, and unaligned address access. When an exception occurs, the CPU suspends the current program, handles the exception, and then continues to execute the program interrupted by the exception.
The following uses the ARMv7-a architecture as an example. The interrupt vector table is the entry for interrupt and exception handling. The interrupt vector table contains the entry function for each interrupt and exception handling. The following uses the ARMv7-a architecture as an example. The interrupt vector table is the entry for interrupt and exception handling. The interrupt vector table contains the entry function for each interrupt and exception handling.
**Figure 1** Interrupt vector table<a name="fig1552753243714"></a> **Figure 1** Interrupt vector table
![](figures/interrupt-vector-table.png "interrupt-vector-table") ![](figures/interrupt-vector-table.png "interrupt-vector-table")
## Development Guidelines<a name="section15415165510110"></a>
## Development Guidelines
### Available APIs<a name="section57441612024"></a>
Exception handling is an internal mechanism and does not provide external APIs. The following table describes APIs available for the interrupt module. ### Available APIs
<a name="table11657113333110"></a> Exception handling is an internal mechanism and does not provide external APIs. The following tables describe the APIs available for the interrupt module.
<table><thead align="left"><tr id="row1170612337312"><th class="cellrowborder" valign="top" width="19.900000000000002%" id="mcps1.1.4.1.1"><p id="p4706133373112"><a name="p4706133373112"></a><a name="p4706133373112"></a><strong id="b7792162213202"><a name="b7792162213202"></a><a name="b7792162213202"></a>Function</strong></p>
</th> ##### Creating or Deleting an Interrupt
<th class="cellrowborder" valign="top" width="18.43%" id="mcps1.1.4.1.2"><p id="p1070653343117"><a name="p1070653343117"></a><a name="p1070653343117"></a><strong id="b19958356201"><a name="b19958356201"></a><a name="b19958356201"></a>API</strong></p>
</th> | API | Description |
<th class="cellrowborder" valign="top" width="61.67%" id="mcps1.1.4.1.3"><p id="p370613330311"><a name="p370613330311"></a><a name="p370613330311"></a><strong id="b1551072610204"><a name="b1551072610204"></a><a name="b1551072610204"></a>Description</strong></p> |------------ | ----------------------------------------------------------- |
</th> | LOS_HwiCreate | Creates an interrupt and registers the interrupt ID, triggering mode, priority, and interrupt handler. When the interrupt is triggered, the interrupt handler will be called.|
</tr> | LOS_HwiDelete | Deletes an interrupt based on the interrupt number. |
</thead>
<tbody><tr id="row8706123317311"><td class="cellrowborder" rowspan="2" valign="top" width="19.900000000000002%" headers="mcps1.1.4.1.1 "><p id="p4706193319318"><a name="p4706193319318"></a><a name="p4706193319318"></a>Creating or deleting interrupts</p> ##### Enabling or Disabling Interrupts
</td>
<td class="cellrowborder" valign="top" width="18.43%" headers="mcps1.1.4.1.2 "><p id="p170683310317"><a name="p170683310317"></a><a name="p170683310317"></a>LOS_HwiCreate</p> | API | Description |
</td> | -------------- | ------------------------------------------- |
<td class="cellrowborder" valign="top" width="61.67%" headers="mcps1.1.4.1.3 "><p id="p15706833163110"><a name="p15706833163110"></a><a name="p15706833163110"></a>Creates an interrupt and registers the interrupt ID, interrupt triggering mode, interrupt priority, and interrupt handler. When an interrupt is triggered, the interrupt handler will be called.</p> | LOS_IntUnlock | Enables all interrupts for the current processor. |
</td> | LOS_IntLock | Disables all interrupts for the current processor. |
</tr> | LOS_IntRestore | Restores the status in which the system was before **LOS_IntLock** is called.|
<tr id="row18706153318316"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p1870615332312"><a name="p1870615332312"></a><a name="p1870615332312"></a>LOS_HwiDelete</p>
</td> ##### Obtaining Interrupt Information
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p770616333313"><a name="p770616333313"></a><a name="p770616333313"></a>Deletes an interrupt.</p>
</td> | API | Description |
</tr> | ----------------------- | ------------------------ |
<tr id="row1370633316316"><td class="cellrowborder" rowspan="3" valign="top" width="19.900000000000002%" headers="mcps1.1.4.1.1 "><p id="p970611333318"><a name="p970611333318"></a><a name="p970611333318"></a>Enabling and disabling all interrupts</p> | LOS_GetSystemHwiMaximum | Obtains the maximum number of interrupts supported by the system.|
</td>
<td class="cellrowborder" valign="top" width="18.43%" headers="mcps1.1.4.1.2 "><p id="p147061033103117"><a name="p147061033103117"></a><a name="p147061033103117"></a>LOS_IntUnLock</p>
</td>
<td class="cellrowborder" valign="top" width="61.67%" headers="mcps1.1.4.1.3 "><p id="p93681327171713"><a name="p93681327171713"></a><a name="p93681327171713"></a>Enables all interrupts of the current processor.</p> ### How to Develop
</td>
</tr> 1. Call **LOS_HwiCreate** to create an interrupt.
<tr id="row1270603314312"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p1970623343114"><a name="p1970623343114"></a><a name="p1970623343114"></a>LOS_IntLock</p>
</td> 2. Call **LOS_HwiDelete** to delete the specified interrupt. Use this API based on actual requirements.
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p1161283971712"><a name="p1161283971712"></a><a name="p1161283971712"></a>Disables all interrupts for the current processor.</p>
</td>
</tr> ### Development Example
<tr id="row8706233173113"><td class="cellrowborder" valign="top" headers="mcps1.1.4.1.1 "><p id="p1770620337313"><a name="p1770620337313"></a><a name="p1770620337313"></a>LOS_IntRestore</p>
</td>
<td class="cellrowborder" valign="top" headers="mcps1.1.4.1.2 "><p id="p1470643323112"><a name="p1470643323112"></a><a name="p1470643323112"></a>Restores to the status before all interrupts are disabled by using <strong id="b354311504226"><a name="b354311504226"></a><a name="b354311504226"></a>LOS_IntLock</strong>.</p>
</td>
</tr>
<tr id="row870793320317"><td class="cellrowborder" valign="top" width="19.900000000000002%" headers="mcps1.1.4.1.1 "><p id="p1970763318316"><a name="p1970763318316"></a><a name="p1970763318316"></a>Obtaining the maximum number of interrupts supported</p>
</td>
<td class="cellrowborder" valign="top" width="18.43%" headers="mcps1.1.4.1.2 "><p id="p1707333123115"><a name="p1707333123115"></a><a name="p1707333123115"></a>LOS_GetSystemHwiMaximum</p>
</td>
<td class="cellrowborder" valign="top" width="61.67%" headers="mcps1.1.4.1.3 "><p id="p4707173323111"><a name="p4707173323111"></a><a name="p4707173323111"></a>Obtains the maximum number of interrupts supported by the system.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section64332181221"></a>
1. Call **LOS\_HwiCreate** to create an interrupt.
2. Call **LOS\_HwiDelete** to delete the specified interrupt. Use this API based on actual requirements.
### Development Example<a name="section204698276478"></a>
This example implements the following: This example implements the following:
1. Create an interrupt.
2. Delete an interrupt.
The following sample code shows how to create and delete an interrupt. When the interrupt **HWI\_NUM\_TEST** is generated, the interrupt handler function will be called. 1. Create an interrupt.
``` 2. Delete an interrupt.
The following sample code demostrates how to create and delete an interrupt, and call the interrupt handler when the specified interrupt **HWI_NUM_TEST** is triggered. You can add the test function of the sample code to **TestTaskEntry** in **kernel/liteos_a/testsuites/kernel/src/osTest.c** for testing.
The sample code is as follows:
```c
#include "los_hwi.h" #include "los_hwi.h"
/* Interrupt handler function*/ /* Interrupt handler function*/
STATIC VOID HwiUsrIrq(VOID) STATIC VOID HwiUsrIrq(VOID)
{ {
printf("in the func HwiUsrIrq \n"); PRINTK("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; // The interrupt number is 7.
HWI_PRIOR_T hwiPrio = 3; HWI_PRIOR_T hwiPrio = 3; // The interrupt priority is 3.
HWI_MODE_T mode = 0; HWI_MODE_T mode = 0;
HWI_ARG_T arg = 0; HWI_ARG_T arg = 0;
/* Create an interrupt.*/ /* Create an interrupt. */
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"); PRINTK("Hwi create success!\n");
} else { } else {
printf("Hwi create failed!\n"); PRINTK("Hwi create failed!\n");
return LOS_NOK; return LOS_NOK;
} }
/* Delay 50 ticks. When a hardware interrupt occurs, call the HwiUsrIrq function.*/ /* Delay 50 ticks. Call HwiUsrIrq when a hardware interrupt occurs. */
LOS_TaskDelay(50); LOS_TaskDelay(50);
/* Delete an interrupt./ /* Delete the interrupt. */
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"); PRINTK("Hwi delete success!\n");
} else { } else {
printf("Hwi delete failed!\n"); PRINTK("Hwi delete failed!\n");
return LOS_NOK; return LOS_NOK;
} }
return LOS_OK; return LOS_OK;
} }
``` ```
### Verification<a name="section1466144215476"></a>
### Verification
The development is successful if the return result is as follows: The development is successful if the return result is as follows:
...@@ -134,4 +133,3 @@ The development is successful if the return result is as follows: ...@@ -134,4 +133,3 @@ The development is successful if the return result is as follows:
Hwi create success! Hwi create success!
Hwi delete success! Hwi delete success!
``` ```
# Scheduler # Scheduler
## Basic Concepts<a name="section123882355719"></a> ## Basic Concepts
The OpenHarmony LiteOS-A kernel uses the preemptive scheduling mechanism for tasks. The tasks with a higher priority are scheduled first, and the tasks with the same priority are scheduled using the time slice polling. The system runs based on the real-time timeline from the startup, which ensures good real-time performance of the scheduling algorithm. The OpenHarmony LiteOS-A kernel uses the preemptive scheduling mechanism for tasks. The tasks with a higher priority are scheduled first, and the tasks with the same priority are scheduled using the time slice polling. The system runs based on the real-time timeline from the startup, which ensures good real-time performance of the scheduling algorithm.
The OpenHarmony scheduling algorithm is embedded with the tickless mechanism, which ensures lower power consumption and on-demand response to tick interrupts. This minimizes useless tick interrupt response time and further improves the real-time performance of the system. The OpenHarmony scheduling algorithm is embedded with the tickless mechanism, which ensures lower power consumption and on-demand response to tick interrupts. This minimizes useless tick interrupt response time and further improves the real-time performance of the system.
The OpenHarmony process scheduling policy is **SCHED\_RR**, and the thread scheduling policy can be **SCHED\_RR** or **SCHED\_FIFO**. OpenHarmony supports **SCHED_RR** (time slice round robin) for process scheduling and **SCHED_RR** and **SCHED_FIFO** (first in, first out) for thread scheduling .
Threads are the minimum scheduling units in the OpenHarmony. Threads are the minimum scheduling units in OpenHarmony.
## Working Principles<a name="section143015396572"></a>
The OpenHarmony uses process priority queue and thread priority queue for scheduling. The process priority ranges from 0 to 31, and there are 32 process priority bucket queues. Each bucket queue corresponds to a thread priority bucket queue. The thread priority ranges from 0 to 31, and a thread priority bucket queue also has 32 priority queues. ## Working Principles
OpenHarmony uses process priority queue and thread priority queue for scheduling. The process priority ranges from 0 to 31, and there are 32 process priority bucket queues. Each bucket queue corresponds to a thread priority bucket queue. The thread priority ranges from 0 to 31, and a thread priority bucket queue also has 32 priority queues.
**Figure 1** Scheduling priority bucket queue
**Figure 1** Scheduling priority bucket queue<a name="fig124425991619"></a>
![](figures/scheduling-priority-bucket-queue.png "scheduling-priority-bucket-queue") ![](figures/scheduling-priority-bucket-queue.png "scheduling-priority-bucket-queue")
The OpenHarmony system starts scheduling after the kernel initialization is complete. The processes or threads created during running are added to the scheduling queues. The system selects the optimal thread for scheduling based on the priorities of the processes and threads and the time slice consumption of the threads. Once a thread is scheduled, it is deleted from the scheduling queue. If a thread is blocked during running, the thread is added to the corresponding blocking queue and triggers scheduling of another thread. If no thread in the scheduling queue can be scheduled, the system selects the thread of the KIdle process for scheduling. The OpenHarmony system starts scheduling after the kernel initialization is complete. The processes or threads created during running are added to the scheduling queues. The system selects the optimal thread for scheduling based on the priorities of the processes and threads and the time slice consumption of the threads. Once a thread is scheduled, it is deleted from the scheduling queue. If a thread is blocked during running, the thread is added to the corresponding blocking queue and triggers scheduling of another thread. If no thread in the scheduling queue can be scheduled, the system selects the thread of the KIdle process for scheduling.
**Figure 2** Scheduling process<a name="fig1163494931810"></a> **Figure 2** Scheduling process
![](figures/scheduling-process.png "scheduling-process") ![](figures/scheduling-process.png "scheduling-process")
## Development Guidelines<a name="section10604192145816"></a>
### Available APIs<a name="section207985910582"></a>
<a name="table687929113814"></a>
<table><thead align="left"><tr id="row513082983812"><th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.1"><p id="p121309298384"><a name="p121309298384"></a><a name="p121309298384"></a><strong id="b1684811125913"><a name="b1684811125913"></a><a name="b1684811125913"></a>Function</strong></p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.2"><p id="p713082933817"><a name="p713082933817"></a><a name="p713082933817"></a>API</p>
</th>
<th class="cellrowborder" valign="top" width="33.33333333333333%" id="mcps1.1.4.1.3"><p id="p20130829123810"><a name="p20130829123810"></a><a name="p20130829123810"></a><strong id="b66639257454"><a name="b66639257454"></a><a name="b66639257454"></a>Description</strong></p>
</th>
</tr>
</thead>
<tbody><tr id="row713032973813"><td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.1 "><p id="p0130429133818"><a name="p0130429133818"></a><a name="p0130429133818"></a>System scheduling</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.2 "><p id="p71581556124414"><a name="p71581556124414"></a><a name="p71581556124414"></a>LOS_Schedule</p>
</td>
<td class="cellrowborder" valign="top" width="33.33333333333333%" headers="mcps1.1.4.1.3 "><p id="p181303297387"><a name="p181303297387"></a><a name="p181303297387"></a>Triggers system scheduling.</p>
</td>
</tr>
</tbody>
</table>
### How to Develop<a name="section1015110331584"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Scheduling cannot be triggered during the system initialization process.
## Development Guidelines
### Available APIs
| API| Description|
| -------- | -------- |
| LOS_Schedule | Triggers system scheduling.|
| LOS_GetTaskScheduler | Obtains the scheduling policy of a task.|
| LOS_SetTaskScheduler | Sets the scheduling policy for a task.|
| LOS_GetProcessScheduler | Obtains the scheduling policy of a process.|
| LOS_SetProcessScheduler | Sets scheduling parameters, including the priority and scheduling policy, for a process.|
### How to Develop
> **NOTE**
>
> Scheduling cannot be triggered during the system initialization process.
...@@ -3,20 +3,22 @@ ...@@ -3,20 +3,22 @@
## Kernel Startup Process ## Kernel Startup Process
The kernel startup process consists of the assembly startup and C language startup, as shown in the following figure. The kernel startup process consists of the assembly startup and C language startup, as shown in **Figure 1**.
The assembly startup involves the following operations: initializing CPU settings, disabling dCache/iCache, enabling the FPU and NEON, setting the MMU to establish the virtual-physical address mapping, setting the system stack, clearing the BSS segment, and calling the main function of the C language. The assembly startup involves the following operations: initializing CPU settings, disabling dCache/iCache, enabling the FPU and NEON, setting the MMU to establish the virtual-physical address mapping, setting the system stack, clearing the BSS segment, and calling the main function of the C language.
The C language startup involves the following operations: starting the **OsMain** function and starting scheduling. As shown in the following figure, the **OsMain** function is used for basic kernel initialization and architecture- and board-level initialization. The kernel startup framework leads the initialization process. The right part of the figure shows the phase in which external modules can register with the kernel startup framework and starts. The table below describes each phase. The C language startup involves the following operations: starting the **OsMain** function and starting scheduling.
**OsMain()** is used for basic kernel initialization and architecture- and board-level initialization. The kernel startup framework leads the initialization process. The right part of the figure shows the phase in which external modules can register with the kernel startup framework and starts. **Table 1** describes each phase.
**Figure 1** Kernel startup process<br> **Figure 1** Kernel startup process
![](figures/kernel-startup-process-2.png "kernel-startup-process-2")
![](figures/kernel-startup-process-2.png "kernel-startup-process-2")
**Table 1** Start framework
| Level | Startup Description | **Table 1** Kernel startup framework
| API| Description|
| -------- | -------- | | -------- | -------- |
| LOS_INIT_LEVEL_EARLIEST | Earliest initialization.<br>The initialization is architecture-independent. The board and subsequent modules initialize the pure software modules on which they depend.<br>Example: trace module| | LOS_INIT_LEVEL_EARLIEST | Earliest initialization.<br>The initialization is architecture-independent. The board and subsequent modules initialize the pure software modules on which they depend.<br>Example: trace module|
| LOS_INIT_LEVEL_ARCH_EARLY | Early initialization of the architecture.<br>The initialization is architecture-dependent. Subsequent modules initialize the modules on which they depend. It is recommended that functions not required for startup be placed at **LOS_INIT_LEVEL_ARCH**.| | LOS_INIT_LEVEL_ARCH_EARLY | Early initialization of the architecture.<br>The initialization is architecture-dependent. Subsequent modules initialize the modules on which they depend. It is recommended that functions not required for startup be placed at **LOS_INIT_LEVEL_ARCH**.|
...@@ -28,54 +30,52 @@ The C language startup involves the following operations: starting the **OsMain* ...@@ -28,54 +30,52 @@ The C language startup involves the following operations: starting the **OsMain*
| LOS_INIT_LEVEL_KMOD_BASIC | Initialization of the kernel basic modules.<br>Initialize the basic modules that can be detached from the kernel.<br>Example: VFS initialization| | LOS_INIT_LEVEL_KMOD_BASIC | Initialization of the kernel basic modules.<br>Initialize the basic modules that can be detached from the kernel.<br>Example: VFS initialization|
| LOS_INIT_LEVEL_KMOD_EXTENDED | Initialization of the kernel extended modules.<br>Initialize the extended modules that can be detached from the kernel.<br>Example: initialization of system call, ProcFS, Futex, HiLog, HiEvent, and LiteIPC| | LOS_INIT_LEVEL_KMOD_EXTENDED | Initialization of the kernel extended modules.<br>Initialize the extended modules that can be detached from the kernel.<br>Example: initialization of system call, ProcFS, Futex, HiLog, HiEvent, and LiteIPC|
| LOS_INIT_LEVEL_KMOD_TASK | Kernel task creation.<br>Create kernel tasks (kernel tasks and software timer tasks).<br>Example: creation of the resident resource reclaiming task, SystemInit task, and CPU usage statistics task| | LOS_INIT_LEVEL_KMOD_TASK | Kernel task creation.<br>Create kernel tasks (kernel tasks and software timer tasks).<br>Example: creation of the resident resource reclaiming task, SystemInit task, and CPU usage statistics task|
| LOS_INIT_LEVEL_FINISH | Complete of the kernel initialization.|
## Programming Example ## Development Example
**Example Description** **Example Description**
Add a kernel module and register the initialization function of the module to the kernel startup process through the kernel startup framework, so as to complete the module initialization during the kernel initialization process. Add a kernel module and register the initialization function of the module to the kernel startup process through the kernel startup framework, so as to complete the module initialization during the kernel initialization process.
You can compile and verify the sample code in **kernel/liteos_a/testsuites/kernel/src/osTest.c**.
**Sample Code** **Sample Code**
```c
```
/* Header file of the kernel startup framework */ /* Header file of the kernel startup framework */
#include "los_init.h" #include "los_init.h"
...
/* Initialization function of the new module */ /* Initialization function of the new module */
unsigned int OsSampleModInit(void) unsigned int OsSampleModInit(void)
{ {
PRINTK("OsSampleModInit SUCCESS!\n"); PRINTK("OsSampleModInit SUCCESS!\n");
......
} }
...
/* Register the new module at the target level of the kernel startup framework. */ /* Register the new module at the target level of the kernel startup framework. */
LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED);
``` ```
**Verification** **Verification**
``` ```
main core booting up... main core booting up...
/* The print information may vary depending on the running environment. */
...
/* Print the initialization function of the new module in the test code. */
OsSampleModInit SUCCESS! OsSampleModInit SUCCESS!
releasing 1 secondary cores
cpu 1 entering scheduler
cpu 0 entering scheduler
``` ```
According to the information displayed during the system startup, the kernel has called the initialization function of the registered module during the startup to initialize the module. According to the information displayed during the system startup, the kernel calls the initialization function of the registered module during the startup to initialize the module.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE** > **NOTE**
> >
> Modules at the same level cannot depend on each other. It is recommended that a new module be split based on the preceding startup phase and be registered and started as required. > Modules of the same level cannot depend on each other. It is recommended that a new module be split based on the preceding startup phase and be registered and started as required.
> >
> You can view the symbol table in the **.rodata.init.kernel.*** segment of the **OHOS_Image.map** file generated after the build is complete, so as to learn about the initialization entry of each module that has been registered with the kernel startup framework and check whether the newly registered initialization entry has taken effect. > You can view the symbol table in the **.rodata.init.kernel.*** segment of the **OHOS_Image.map** file generated after the build is complete, so as to learn about the initialization entry of each module that has been registered with the kernel startup framework and check whether the newly registered initialization entry has taken effect.
# Startup in User Mode # Startup in User Mode
## Startup of the Root Process in User Mode<a name="section79911135647"></a>
## Startup of the Root Process in User Mode
The root process is the first user-mode process in the system. The process ID is 1. The root process is the ancestor of all user-mode processes. The root process is the first user-mode process in the system. The process ID is 1. The root process is the ancestor of all user-mode processes.
**Figure 1** Process tree<a name="fig427516409375"></a> **Figure 1** Process tree
![](figures/process-tree.png "process-tree") ![](figures/process-tree.png "process-tree")
### Startup Process of the Root Process<a name="section1184317581349"></a>
### Startup Process of the Root Process
Use the link script to place the following init startup code to the specified location in the system image. Use the link script to place the following init startup code to the specified location in the system image.
```
```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)
{ {
...@@ -23,38 +27,38 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args) ...@@ -23,38 +27,38 @@ LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
} }
``` ```
During system startup, **OsUserInitProcess** is called to start the **init** process. The procedure is as follows: > **NOTE**
>
> The preceeding code is in **kernel/liteos_a/kernel/user/src/los_user_init.c**. The value of **g_initPath** can be **/dev/shm/init** or **/bin/init**, depending on the startup settings.
1. The kernel calls **OsLoadUserInit** to load the code. Use **OsUserInitProcess** to start the **init** process. The procedure is as follows:
2. A process space is created to start the **/bin/init** process.
### Responsibilities of the Root Process<a name="section1590220321759"></a> 1. The kernel calls **OsLoadUserInit** to load the code for startup.
- Starts key system programs or services, such as shell. 2. A process space is created to start the **/bin/init** process.
>![](../public_sys-resources/icon-note.gif) **NOTE**
>
>In OpenHarmony, the **init** process reads the **/etc/init.cfg** file and runs specified commands or starts specified processes based on configurations. For details, see [init Module](../subsystems/subsys-boot-init-cfg.md).
### Responsibilities of the Root Process
- Monitors the process for reclaiming the orphan process and clears the zombie processes in child processes. - The root process starts key system programs or services, such as shell.
> **NOTE**
> In OpenHarmony, the **init** process reads **/etc/init.cfg** and runs commands or starts processes based on the configuration. For details, see [init Configuration File](../subsystems/subsys-boot-init-cfg.md).
## Running Programs in User Mode<a name="section194576310611"></a> - The root process monitors the process for reclaiming the orphan process and clears the zombie processes in child processes.
A user-mode program can be started in either of the following ways: ## Running Programs in User Mode
- Run the shell command to start the process.
```
OHOS $ exec helloworld
OHOS $ ./helloworld
OHOS $ /bin/helloworld
```
A user-mode program can be started in either of the following ways:
- Start a new process by calling the POSIX API. - Using shell commands
Use the **Fork\(\)** method to create a process, and call the **exec\(\)** method to execute a new process. ```
OHOS $ exec helloworld
OHOS $ ./helloworld
OHOS $ /bin/helloworld
```
- Using POSIX APIs
Use **Fork()** to create a process, and call **exec()** to execute a process.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册