Location>code7788 >text

[rCore Study Notes 021] Multi-Channel Programs and Time-Sharing Tasks

Popularity:340 ℃/2024-08-04 00:25:40

write sth. upfront

This essay was written by a very rookie rookie. Please feel free to ask any questions.

You can contact: 1160712160@

GitHhub:/WindDevil (Nothing so far.

guide (e.g. book or other printed material)

Here is the beginning of the third chapter, due to my huge dishes, resulting in half a day can not understand the key points, alas, is too torturous.

Following the fine tradition of the beginning of the last chapter, I personally feel that every time the manual gives the feature to think about the last chapter for this function we are how to realize, now the function is what benefits. This can deepen the impression.

Improving system performance and efficiency is one of the core goals of an operating system, and this chapter shows a number of functional improvements to the operating system in terms of performance:

  • Reduces application switching overhead by loading applications into memory ahead of time
  • Improve system execution efficiency by supporting the active abandonment of processors by programs through collaboration mechanisms
  • The preemption mechanism supports the passive abandonment of the processor by the program, which ensures the fairness of the processor resources used by different programs and further improves the efficiency of the application's response to I/O events.

Likewise, be sure to readofficial documentMaybe I'm not looking at the whole picture.

Here's your own brainstorming on how to realize this.

  1. Methods for loading applications into memory ahead of time.
    1. Use more memory, load all the applications in one go, and return the addresses in memory.
    2. If I don't have all the applications loaded in memory, how do we know which application to run later?
  2. the realization of the collaboration mechanism and the preemption mechanism of the method, the feeling that it is written by the application to give up the processor, but in fact to do the implementation of the time I would like to use a similar way to solve the problem of interruptions, that is, to save the context and then jump that set of things, as for how to calculate the time, it is difficult to think of its internal implementation, I feel that this time it must be used to the timer.

All in all, I still have the same childish idea of APP1->delay->preempt->APP2->APP1 that I had when I was using RT-Thread and FreeRTOS.

This is where a deeper understanding is needed.

This can be done in thehere areRecognizing that, incollaborative mode, which requires the programmer to take the initiative to write aVoluntarily relinquishing the processor The call request.

as forpreemptive , which uses thedisruptions directly interrupts the program, thus ensuring that an application is not interrupted after execution.stretch I'll be sure to give up the processor later. Here's an excerpt.official documentDescription.
The operating system can further utilize some kind of peripheral interrupt (e.g., clock interrupt) with a fixed duration as the time interval to forcefully interrupt the execution of a program, so that a program can only run for a certain period of time (which can be referred to as a time slice, Time Slice) will surely give way to the processor, and the operating system can, after dealing with the peripheral's I/O response, let different applications occupy the processor for execution in different times. The operating system can also evaluate the consumption of processor resources by different applications after processing the I/O responses from peripherals, and by counting the total execution time of the programs occupying the processor. We call this type of operationTime Sharing maybePreemptive multitasking (Multitasking) , which may also be combined together astime division multitasking 。

Here's a thought from the depths of your mind aboutbare metal programming The thing is to use thetimers interrupts to realize time-sharing multiplexing, then and using thepreemptive What is the difference between the time-sharing multiplexing of the

  1. Limited number of timers
  2. Problem solving with soft timers is effective for programs with fixed behaviors and fixed durations, but it is more difficult for programs with a variety of complex branches.

There is also a problem with theWaveform Sampling this kind oftime-sensitive Is it safe to leave it to the OS for this type of task? Or do you need to combinetimer interrupt cap (a poem)OS Dispatch. So how does it work?

A final intercept from the official documentation locating and categorizing this chapter's implementation.
The multi-channel programs and time-sharing multitasking systems described in this chapter share some common features: multiple applications can reside in memory at the same time, and all of them are loaded separately into different areas of memory at system startup. Since there is currently only one processor core in a computer system, at most one application is executing (i.e., is in the running state) at any one time; the remaining applications are in the ready or waiting state and require the kernel to allocate processors to them in order to start executing. Once an application starts executing, it is in the running state.
This chapter focuses on the design and implementation of building supportmultiprogram The Permian "Sawtooth Salamander".1 Primary operating system, supportmultiprogram Triassic "primordial dragons".2 Collaborative operating systems and supporttime division multitasking The Triassic "Coelophysis".3 preemptive operating systems, thus providing a comprehensive and in-depth understanding of the multiple execution environments that can support the running of a batch of applications, and allowing for a generalized abstraction of themandates 、 Task Switching and other operating system concepts.

Practical Experience

Similarly, we can easily utilize therCore-Tutorial-v3Experience the implementation of both operating systems.

First we need to switch to the foldercd ~/App/rCore-Tutorial-v3.

Experience the Multi-Channel Program Operating System

Switch to a multi-channel operating system and run.

git checkout ch3-coop
cd os
make run

Note that if you change the contents of a branch so that you can't switch branches, you can use thegit checkout -- .to discard all changes so that you can switch to the new branch.

Results.

[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
[rustsbi] Implementation     : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name      : riscv-virtio,qemu
[rustsbi] Platform SMP       : 1
[rustsbi] Platform Memory    : 0x80000000..0x88000000
[rustsbi] Boot HART          : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000f02
[rustsbi] Firmware Address   : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[kernel] Hello, world!
AAAAAAAAAA [1/5]
BBBBBBBBBB [1/2]
CCCCCCCCCC [1/3]
AAAAAAAAAA [2/5]
BBBBBBBBBB [2/2]
CCCCCCCCCC [2/3]
AAAAAAAAAA [3/5]
Test write_b OK!
[kernel] Application exited with code 0
CCCCCCCCCC [3/3]
AAAAAAAAAA [4/5]
Test write_c OK!
[kernel] Application exited with code 0
AAAAAAAAAA [5/5]
Test write_a OK!
[kernel] Application exited with code 0
All applications completed!

The result of this run is this [ 1/5 ] means that the execution of the first of the fifth execution, so it is easy to understand the results of this program, that is, taking turns in the execution of all have been loaded into memory, respectively, can output a series ofA,B,Cthree procedures.

Then it is executed until the number of times is limited.

Experience the time-sharing multitasking operating system

cd ~/App/rCore-Tutorial-v3, go back to the root file again, switch to the time-sharing multitasking operating system and run.

git checkout ch3
cd os
make run

Results.

[rustsbi] RustSBI version 0.3.1, adapting to RISC-V SBI v1.0.0
.______       __    __      _______.___________.  _______..______   __
|   _  \     |  |  |  |    /       |           | /       ||   _  \ |  |
|  |_)  |    |  |  |  |   |   (----`---|  |----`|   (----`|  |_)  ||  |
|      /     |  |  |  |    \   \       |  |      \   \    |   _  < |  |
|  |\  \----.|  `--'  |.----)   |      |  |  .----)   |   |  |_)  ||  |
| _| `._____| \______/ |_______/       |__|  |_______/    |______/ |__|
[rustsbi] Implementation     : RustSBI-QEMU Version 0.2.0-alpha.2
[rustsbi] Platform Name      : riscv-virtio,qemu
[rustsbi] Platform SMP       : 1
[rustsbi] Platform Memory    : 0x80000000..0x88000000
[rustsbi] Boot HART          : 0
[rustsbi] Device Tree Region : 0x87000000..0x87000f02
[rustsbi] Firmware Address   : 0x80000000
[rustsbi] Supervisor Address : 0x80200000
[rustsbi] pmp01: 0x00000000..0x80000000 (-wr)
[rustsbi] pmp02: 0x80000000..0x80200000 (---)
[rustsbi] pmp03: 0x80200000..0x88000000 (xwr)
[rustsbi] pmp04: 0x88000000..0x00000000 (-wr)
[kernel] Hello, world!
power_3 [10000/200000]
power_3 [20000/200000]
power_3 [30000/200000]
power_3 [40000/200000]
power_3 [50000/200000]
power_3 [60000/200000]
power_3 [70000/200000]
power_3 [80000/200000]
power_3 [90000/200000]
power_3 [100000/200000]
power_3 [110000/200000]
power_3 [120000/200000]
power_3 [130000/200000]
power_3 [140000/200000]
power_3 [150000/200000]
power_3 [160000/200000]
power_3 [170000/200000]
power_3 [180000/200000]
power_3 [190000/200000]
power_3 [200000/200000]
3^200000 = 871008973(MOD 998244353)
Test power_3 OK!
[kernel] Application exited with code 0
power_5 [10000/140000]
power_5 [20000/140000]
power_5 [30000/140000]
power_5 [40000/140000]
power_5 [50000/140000]
power_5 [60000/140000]
power_5 [70000/140000]
power_5 [80000/140000]
power_5 [90000/140000]
power_5 [100000/140000]
power_5 [110000/140000]
power_5 [120000/140000]
power_7 [10000/160000]
power_7 [20000/160000]
power_7 [30000/160000]
power_7 [40000/160000]
power_7 [50000/160000]
power_7 [60000/160000]
power_7 [70000/160000]
power_7 [80000/160000]
power_7 [90000/160000]
power_7 [100000/160000]
power_7 [110000/160000]
power_7 [120000/160000]
power_7 [130000/160000]
power_7 [140000/160000]
power_7 [150000/160000]
power_7 [160000/160000]
7^160000 = 667897727(MOD 998244353)
Test power_7 OK!
[kernel] Application exited with code 0
power_5 [130000/140000]
power_5 [140000/140000]
5^140000 = 386471875(MOD 998244353)
Test power_5 OK!
[kernel] Application exited with code 0
Test sleep OK!
[kernel] Application exited with code 0
All applications completed!

official documentIt parses as.
There are two types of time-sharing multitasking system applications. The application numbered 00/01/02 calculates the remainder of a large prime number modulo powers of 3/5/7 and outputs the result in stages. The application numbered 03 waits for three seconds before exiting. Using the k210 platform as an example, we will see that application 00/01/02 completes its computation in stages, while application 03 is always the last one to finish due to the long waiting time.

code structure

Here's the chapter.multiprogrammed operating system The code structure of.

This is the code structure of the previous chapter, you can see that this chapter'smultitasking It's a few more app block diagrams inU-Mode:

This is furtherCollaborative time-sharing operating system Block diagram of.

First of all, let's start with my own feelings when I saw this picture.

  1. Adds a context-saving stack to the original multi-channel system for each app.
  2. Split AppManager into Loader and TaskManager.
  3. Added the concept of task state and task context, which is supposed to be used for time-sharing, but I don't know exactly how it's implemented.
  4. Added a timeline for the CPU, supposedly for time-sharing multiplexing, but don't know exactly how it's done.

By looking at theofficial documentWe can additionally add to the list of things we don't know.
If the current application is running, the task corresponding to that application is in the Running state; if the application actively abandons the processor, the task corresponding to that application is in the Ready state. When the operating system switches tasks, it needs to save the context of the task to be paused (i.e., the general-purpose registers used by the task) and restore the context of the task to be continued to what it was before it was paused, so that different applications can use the processor collaboratively.

This is furtherpreemptive multitasking operating system Block diagram of.

Similarly, look at the diagram and tell us what you feel.

  1. At first glance andcollaborative There's no difference.
  2. A closer look reveals that in theTrap_handler, added in theTimerThe scheduler, as I thought, might use a timer to trigger an interrupt and then rotate the time slice.

as a matter of factofficial documentThe description is more or less the same.

Code guide for this chapter

The author of this part is so good, I'm directly speechless. I'm speechless.Click to watchRight.

The focus of this chapter is on implementing operating system support for collaborative and preemptive task switching between applications. Compared to the operating system implementation in the previous chapter, there are a number of differences that lead to differences in the implementation as follows:

  • Multiple applications are placed in memory at the same time, so their starting addresses are different and the address ranges must not overlap
  • The application will pause or be preempted throughout execution, i.e. there will be active or passive task switching

These implementation differences focus on the management of the application execution process, the system calls that support application suspension, and the management of the clock interrupt mechanism required to actively switch applications.

For the first different case, the layout of the application's address space needs to be adjusted, which is different for each application and cannot overlap. This is not done by modifying the application itself, but through a script to modify the linking scripts for each application. hit the nail on the headBASE_ADDRESS to allow the compiler to compile different applications using theBASE_ADDRESS are different and have large enough address intervals. This allows the memory space where each application is located to be different.

For the second different case, a task switch needs to be implemented, which requires a Task context switch on top of the Trap context switch from the previous chapter to complete a full task switch. The key data structure here is the application execution contextTaskContext data structures and assembly language written specifically to accomplish context switching__switch Functions. An application's execution needs to be managed by the operating system, which is done through theTaskControlBlock data structure to represent the dynamic execution process and state (running state, ready state, etc.) of the application execution context. And in order to prepare for the pre-initialization of the first execution of the application, theTaskManager Examples of Global Variables for Data StructuresTASK_MANAGER describes the data required for the initialization of the application, whereas for theTASK_MANAGER The initialization assignment process is a key step in achieving this preparation.

An application can be actively paused during user-state execution, which requires a new system call to thesys_yield implementation to support this; in order to support preemptive switching that preempts application execution, handling of clock interrupts is also added. With clock interrupts, it is possible to interrupt the execution of an application at defined time intervals and actively switch to another application, which is partially supported mainly by the handling of thetrap_handler function is extended to accomplish a possible task switch when a clock interrupt is generated.TaskManager Member Functions of Data Structuresrun_next_task to specifically implement task switching based on task control blocks, and will specifically call the__switch function accomplishes the task context switching for the hardware related parts.