《操作系统》的实验代码。
 
 
 
 
 

6.9 KiB

This program allows you to see how address translations are performed in a system with segmentation. The segmentation that this system uses is pretty simple: an address space has just two segments; further, the top bit of the virtual address generated by the process determines which segment the address is in: 0 for segment 0 (where, say, code and the heap would reside) and 1 for segment 1 (where the stack lives). Segment 0 grows in a positive direction (towards higher addresses), whereas segment 1 grows in the negative direction.

Visually, the address space looks like this:

--------------- virtual address 0 | seg0 | | |

(unallocated)
-------------
seg1
-------------

With segmentation, as you might recall, there is a base/limit pair of registers per segment. Thus, in this problem, there are two base/limit pairs. The segment-0 base tells which physical address the top of segment 0 has been placed in physical memory and the limit tells how big the segment is; the segment-1 base tells where the bottom of segment 1 has been placed in physical memory and the corresponding limit also tells us how big the segment is (or how far it grows in the negative direction).

As before, there are two steps to running the program to test out your understanding of segmentation. First, run without the "-c" flag to generate a set of translations and see if you can correctly perform the address translations yourself. Then, when done, run with the "-c" flag to check your answers.

For example, to run with the default flags, type:

prompt> ./segmentation.py

(or prompt> python ./segmentation.py if that doesn't work)

You should see this: ARG seed 0 ARG address space size 1k ARG phys mem size 16k

Segment register information:

Segment 0 base  (grows positive) : 0x00001aea (decimal 6890)
Segment 0 limit                  : 472

Segment 1 base  (grows negative) : 0x00001254 (decimal 4692)
Segment 1 limit                  : 450

Virtual Address Trace VA 0: 0x0000020b (decimal: 523) --> PA or segmentation violation? VA 1: 0x0000019e (decimal: 414) --> PA or segmentation violation? VA 2: 0x00000322 (decimal: 802) --> PA or segmentation violation? VA 3: 0x00000136 (decimal: 310) --> PA or segmentation violation? VA 4: 0x000001e8 (decimal: 488) --> PA or segmentation violation?

For each virtual address, either write down the physical address it translates to OR write down that it is an out-of-bounds address (a segmentation violation). For this problem, you should assume a simple address space with two segments: the top bit of the virtual address can thus be used to check whether the virtual address is in segment 0 (topbit=0) or segment 1 (topbit=1). Note that the base/limit pairs given to you grow in different directions, depending on the segment, i.e., segment 0 grows in the positive direction, whereas segment 1 in the negative.

Then, after you have computed the translations in the virtual address trace, run the program again with the "-c" flag. You will see the following (not including the redundant information):

Virtual Address Trace VA 0: 0x0000020b (decimal: 523) --> SEGMENTATION VIOLATION (SEG1) VA 1: 0x0000019e (decimal: 414) --> VALID in SEG0: 0x00001c88 (decimal: 7304) VA 2: 0x00000322 (decimal: 802) --> VALID in SEG1: 0x00001176 (decimal: 4470) VA 3: 0x00000136 (decimal: 310) --> VALID in SEG0: 0x00001c20 (decimal: 7200) VA 4: 0x000001e8 (decimal: 488) --> SEGMENTATION VIOLATION (SEG0)

As you can see, with -c, the program translates the addresses for you, and hence you can check if you understand how a system using segmentation translates addresses.

Of course, there are some parameters you can use to give yourself different problems. One particularly important parameter is the -s or -seed parameter, which lets you generate different problems by passing in a different random seed. Of course, make sure to use the same random seed when you are generating a problem and then solving it.

There are also some parameters you can use to play with different-sized address spaces and physical memories. For example, to experiment with segmentation in a tiny system, you might type:

prompt> ./segmentation.py -s 100 -a 16 -p 32 ARG seed 0 ARG address space size 16 ARG phys mem size 32

Segment register information:

Segment 0 base  (grows positive) : 0x00000018 (decimal 24)
Segment 0 limit                  : 4

Segment 1 base  (grows negative) : 0x00000012 (decimal 18)
Segment 1 limit                  : 5

Virtual Address Trace VA 0: 0x0000000c (decimal: 12) --> PA or segmentation violation? VA 1: 0x00000008 (decimal: 8) --> PA or segmentation violation? VA 2: 0x00000001 (decimal: 1) --> PA or segmentation violation? VA 3: 0x00000007 (decimal: 7) --> PA or segmentation violation? VA 4: 0x00000000 (decimal: 0) --> PA or segmentation violation?

which tells the program to generate virtual addresses for a 16-byte address space placed somewhere in a 32-byte physical memory. As you can see, the resulting virtual addresses are tiny (12, 8, 1, 7, and 0). As you can also see, the program picks tiny base register and limit values, as appropriate. Run with -c to see the answers.

This example should also show you exactly what each base pair means. For example, segment 0's base is set to a physical address of 24 (decimal) and is of size 4 bytes. Thus, virtual addresses 0, 1, 2, and 3 are in segment 0 and valid, and map to physical addresses 24, 25, 26, and 27, respectively.

Slightly more tricky is the negative-direction-growing segment 1. In the tiny example above, segment 1's base register is set to physical address 18, with a size of 5 bytes. That means that the last five bytes of the virtual address space, in this case 11, 12, 13, 14, and 15, are valid virtual addresses, and that they map to physical addresses 13, 14, 15, 16, and 17, respectively.

If that doesn't make sense, read it again -- you will have to make sense of how this works in order to do any of these problems.

Note you can specify bigger values by tacking a "k", "m", or even "g" onto the values you pass in with the -a or -p flags, as in "kilobytes", "megabytes", and "gigabytes". Thus, if you wanted to do some translations with a 1-MB address space set in a 32-MB physical memory, you might type:

prompt> ./segmentation.py -a 1m -p 32m

If you want to get even more specific, you can set the base register and limit register values yourself, with the --b0, --l0, --b1, and --l1 registers. Try them and see.

Finally, you can always run

prompt> ./segmentation.py -h

to get a complete list of flags and options.

Enjoy!