Segmentation
- What are some limitations of the base/limit system?
- Where is there waste?
- Inside a process’s address space
- Where specifically?
- Between code and data
- Between stack and heap
- This is called internal fragmentation
- How can we address this?
- Break up an address space into multiple pieces (aka segments)
- For example, code, stack, heap
- Important: The process still has only a single virtual address space.
However, areas of that virtual address space don’t actually correspond to
physical memory
- What are the challenges?
- The address translation system needs to figure out which segment an address is in?
- Given a virtual address, what are some ways we can identify a segment?
- Remember, this has to be fast
- Use first few bits of the address. (Explicit approach)
- Pros? Cons?
- Fast, but becomes a hard-wired number of segments.
- Also limits segment size to
1/2^n of address space.
- Notice that the code/stack/heap approach requires two bits,
which leaves one of the four patterns unused. This can “waste”
part of the address space.
- Suggest a minor adjustment to address this problem.
- Just use two segments: code/heap and stack.
- Why does this work well?
- Code is a fixed size. We know code size at compile time, so we
can just put heap after it.
- Another option: Implicit approach
- Choose the segment based on the source of the address:
- PC -> code segment
- %esp -> stack segment
- else -> heap segment.
Sharing
- Segmentation can allow for sharing of read-only segments (e.g., code).
- This can save physical memory.
- When might this be useful?
- Co-operating processes.
- Think about what might happen during a
fork()
- Think about how this might make the
fork()/exec() model a little less inefficient.
- Different users running the same program (e.g., Chrome)
- This can be handled by OS completely behind the scenes.
Course-grained vs. fine grained segments
- Small numbers of segments considered “course grained” (like above)
- We could also have many segments.
- Need a segment table.
- Could rely on the compiler to make segments explicit when generating addresses.
- What is the benefit of this?
- Could delay assigning a segment to physical memory until that memory is actually used.
- This could be more work at context switch time (save/load the entire segment table)
- How big should segments be? Pros/Cons
- What happens when they need to grow? Is this expensive?
Fragmentation
- Internal fragmentation: Segment is too big and space goes unused.
- External fragmentation: Lots of room between segments, but not enough room in one place.
- Notice the tension: Fewer, larger segments are easier to manage, but have lots of internal fragmentation.