Location>code7788 >text

[rCore Study Notes 027] Address Spaces

Popularity:80 ℃/2024-09-19 11:21:20

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.

introductory

It's the beginning of a new chapter, or the first thing to read.Official HandbookTheoretical presentation and content of the program.

The main point here is to summarize some of the content, which is presented below under smaller headings.

Purpose of this chapter

This chapter demonstrates the range of features that the operating system extends in order to realize the "ideal".

  • Enhances the efficiency of the application's dynamic use of memory through dynamic memory allocation
  • Simplifies the compiler's address space setup for applications through the virtual-real memory mapping mechanism of page tables
  • Enhances memory isolation between applications and between applications and the kernel through the virtual-real memory mapping mechanism of the page table, which strengthens system security.
  • Through the virtual-real memory mapping mechanism of the page table, null-split reuse can be realized(proposed but not realized)

demand (economics)

In the perspective of most applications (i.e., application developers), they take up an entire CPU and a specific (contiguous or non-contiguous) amount of memory space. Of course, we know from the previous chapter that in modern operating systems, we rarely let exclusive CPU usage happen for reasons of fairness. So what an application thinks is an exclusive CPU is just what the kernel wants the application to see.phantom (Illusion), and CPU computational resources are beingtime-division multiplexing (TDM, Time-Division Multiplexing) is hidden by the kernel through proper abstraction and is not visible to the application.

In contrast, we currently do not extend the memory management functionality further than just putting the program into physical memory somewhere. In terms of memory access, all applications access physical memory directly through physical addresses, which makes it inconvenient for application developers to access memory by needing to understand the cumbersome physical address space layout. In the previous chapter, for task switching purposes, all applications were loaded into memory during the initialization phase and simultaneously resided until they all finished running. Moreover, all applications accessed physical memory directly through physical addresses.

This can cause the following problems:

  • First, the memory access interface provided by the kernel to the application is not transparent enough and does not work well. Since theThe application accesses physical memory directly, which requires it to be built with a clear understanding of the layout of the physical memory space of the computer it is running on, as well as planning which address it needs to be loaded to run inIn order to avoid conflicts, it may be necessary for app developers to negotiate this. Avoiding conflicts may also require the developers of the application to negotiate this, which is obviously something that is not common enough and extremely cumbersome today.
  • Second, the kernel does not perform any access behaviors on the application'sprotective measure, each application has read and write access to the entire physical memory in the computer system.Even if the application is restricted to run at the U privilege level, it can still cause a lot of problemsFor example, it can read and write to other applications to steal information or disrupt the normal operation of other applications; it can even modify kernel code snippets to replace originaltrap_handler function to hold the kernel hostage to execute malicious code. In short, this causes the system to be both insecure and unstable.
  • Once again, the current application ofThe memory usage space is already limited before it is run.The kernel does not have the flexibility to give runtime dynamically available memory space to applications. For example, when an application ends, the space occupied by this application is freed, but this space is not dynamically available to other applications that are still running.

prescription

In order to simplify the application development and prevent the application from doing anything wrong, this chapter will better manage the physical memory and provide the application with an abstraction of a more transparent and easy to use, but also more secure access to the memory interface, which is based on the paging mechanism of the virtual memory. From the application's point of view, there is a very large readable/writable/executable Address Space starting at address 0. From the OS's point of view, each application is confined to the physical memory space allocated to it, and cannot read or write to the memory space where other applications and the OS reside. The operating system is located in the memory space where the other applications and the operating system are located.

Hardware Support

The first step in realizing the address space is to implement the paging mechanism and establish a good page mapping relationship between virtual memory and physical memory. This process requires hardware support, hardware details related to the specific CPU, involving address mapping mechanism, etc., relatively complex.

Issues for reflection

Overall, we need to think about the following questions:

  • What is the range of physical memory in hardware?
  • What physical memory spaces require page mapping relationships?
  • How do I create a page table to enable the paging mechanism?
  • How do I ensure that the OS can address and execute code at different times before and after the paging mechanism is enabled?
  • Where is the starting address of the page catalog table (level 1) set?
  • Where is the starting address of the secondary/tertiary etc. page table set and how much space is required?
  • How to set the contents of page catalog table entries/page table entries?
  • If each task is to have its own address space, does each task have to have its own page table?
  • Do the tasks representing the application and the operating system need to have their own page tables?
  • With a page table in place, how should data be passed between the task and the operating system?

experiential session

Classically switch the code to the chapter 4 branch, and then run it in one fell swoop.

cd ~/App/rCore-Tutorial-v3
git checkout ch4
cd os
make run

Note here that if you can't switch toch4Most likely this is because the branch was not discarded or saved, try using thegit checkout .Directive.

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!
.text [0x80200000, 0x8020c000)
.rodata [0x8020c000, 0x80210000)
.data [0x80210000, 0x80266000)
.bss [0x80266000, 0x80577000)
mapping .text section
mapping .rodata section
mapping .data section
mapping .bss section
mapping physical memory
mapping memory-mapped registers
[kernel] back to world!
remap_test passed!
init TASK_MANAGER
num_app = 7
power_3 [10000/300000]
power_3 [20000/300000]
power_3 [30000/300000]
power_3 [40000/300000]
power_3 [50000/300000]
power_3 [60000/300000]
power_3 [70000/300000]
power_3 [80000/300000]
power_3 [90000/300000]
power_3 [100000/300000]
power_3 [110000/300000]
power_3 [120000/300000]
power_3 [130000/300000]
power_3 [140000/300000]
power_3 [150000/300000]
power_3 [160000/300000]
power_3 [170000/300000]
power_3 [180000/300000]
power_3 [190000/300000]
power_3 [200000/300000]
power_3 [210000/300000]
power_3 [220000/300000]
power_3 [230000/300000]
power_3 [240000/300000]
power_3 [250000/300000]
power_3 [260000/300000]
power_3 [270000/300000]
power_3 [280000/300000]
power_3 [290000/300000]
power_3 [300000/300000]
3^300000 = 612461288(MOD 998244353)
Test power_3 OK!
[kernel] Application exited with code 0
power_5 [10000/210000]
power_5 [20000/210000]
power_5 [30000/210000]
power_5 [40000/210000]
power_5 [50000/210000]
power_5 [60000/210000]
power_5 [70000/210000]
power_5 [80000/210000]
power_5 [90000/210000]
power_5 [100000/210000]
power_5 [110000/210000]
power_5 [120000/210000]
power_5 [130000/210000]
power_5 [140000/210000]
power_5 [150000/210000]
power_7 [10000/240000]
power_7 [20000/240000]
power_7 [30000/240000]
power_7 [40000/240000]
power_7 [50000/240000]
power_7 [60000/240000]
power_7 [70000/240000]
power_7 [80000/240000]
power_7 [90000/240000]
power_7 [100000/240000]
power_7 [110000/240000]
power_7 [120000/240000]
power_7 [130000/240000]
power_7 [140000/240000]
power_7 [150000/240000]
power_7 [160000/240000]
power_7 [170000/240000]
power_7 [180000/240000]
power_7 [190000/240000]
power_7 [200000/240000]
power_7 [210000/240000]
power_7 [220000/240000]
power_7 [230000/240000]
power_7 [240000/240000]
7^240000 = 304164893(MOD 998244353)
Test power_7 OK!
[kernel] Application exited with code 0

load_fault APP running...

Into Test load_fault, we will insert an invalid load operation...
Kernel should kill this application!
[kernel] PageFault in application, bad addr = 0x0, bad instruction = 0x100c0, kernel killed it.

store_fault APP running...

Into Test store_fault, we will insert an invalid store operation...
Kernel should kill this application!
[kernel] PageFault in application, bad addr = 0x0, bad instruction = 0x100c0, kernel killed it.
Test sbrk start.
origin break point = 17000
one page allocated,  break point = 18000
try write to allocated page
write ok
10 page allocated,  break point = 22000
11 page DEALLOCATED,  break point = 17000
try DEALLOCATED more one page, should be failed.
Test sbrk almost OK!
now write to deallocated page, should cause page fault.
[kernel] PageFault in application, bad addr = 0x17000, bad instruction = 0x1124a, kernel killed it.
power_5 [160000/210000]
power_5 [170000/210000]
power_5 [180000/210000]
power_5 [190000/210000]
power_5 [200000/210000]
power_5 [210000/210000]
5^210000 = 527227302(MOD 998244353)
Test power_5 OK!
[kernel] Application exited with code 0
Test sleep OK!
[kernel] Application exited with code 0
All applications completed!

Block diagram of the chapter

Here you need to compare the block diagram with the previous chapter to see what improvements have been made in this chapter.

Here's a block diagram of the chapter.

Here's the block diagram from the previous chapter.

The differences that can be seen are divided into two parts.

  1. Different hardware requirements
  2. Different system architectures

hardware requirement

Looking at the block diagram, one can see that the block diagram for this chapter calls for.

  1. CPU with MMU requires the CPU to containMMUThe Memory Management Unit (MMU) is a part of the computer hardware that handles memory management and virtual-to-physical address translation.
  2. MEM with PageTable, request for memorySupport page tablePage Table is a data structure used by the operating system to manage virtual memory, which records the mapping relationship between virtual addresses and physical addresses.Page Table requires hardware support, especially MMU (Memory Management Unit) to realize the fast translation of virtual addresses to physical addresses.

In a nutshell, you need an MMU.

system architecture

Added to the block diagram for this chapter.

  1. Springboard for APP layer and OS layerTrampline
  2. Address space per app
  3. Address space of the kernel
  4. Physical page frame allocation

etc.

Here's an excerpt fromOfficial Handbook:

In terms of concrete implementation, the management scope of TaskManager is extended, and the context Task Context of each Task also includes the address space of that Task, and when switching Tasks, the address space of the Task is also switched. The new memory management module mainly includes page frame allocation and heap allocation related to dynamic memory allocation in the kernel, as well as the type of Apps MemSets that represent the address space of applications and the Kernel MemSet that represents the kernel's own address space.Type.The page table PageTable contained in the MemSet type establishes a real-virtual address mapping relationship, while the other MemArea represents the legal spatial extent of the task.

suggestion

The order in which the code is read for referenceOfficial Handbook.

There is a lot of code here, especially when it comes to memory transformations, which can lead to extensive rewriting of all the previous data structures.trapand the treatment of__switchReconfiguration of .

It is advisable to read the code and make sense of the problems so that you can get through this most difficult chapter.