0

Heap allocators are responsible for actively requesting memory from the OS to grow the heap, e.g., with brk or mmap. Accessing unallocated memory leads to segfaults.

I could design a different OS-user interface, where users could freely read/write anywhere in their 64bit address space (except for executable-no-write pages that hold .text, and kernel reserved sections), and any reads/writes to unallocated memory would, as now, pagefault/segfault, but the OS would trap these read/writes automatically allocate these pages and resume program execution.

The current state-of-the-art seems to leak abstractions. Virtual addressing seems to promise users that they can live in their own address space and do whatever they need to to take care of business (outside program text/ reserved addresses), but we have this leaky abstraction where users need to ask the OS themselves to allocate pages and set read/write/execute bits.

It's like virtual addressing has managed successfully to isolate processes from each other, but still fails to isolate processes from OS-layer and hardware memory management.

Why is user code (e.g., libc) responsible for managing a program's own size? Since user code can request any non-reserved address space to be mapped, what's the point of the user needing to do this themselves?

trincot
  • 317,000
  • 35
  • 244
  • 286
Dragonsheep
  • 242
  • 3
  • 10

1 Answers1

2

Since user code can request any non-reserved address space to be mapped, what's the point of the user needing to do this themselves?

There's at least 3 reasons:

a) It's not enough to tell the OS that you want an area of the virtual address space to be accessible, you also need to tell the OS how it should be accessible. "Make the area behave like read/write RAM" is only one possibility - you can ask for the area to be a read-only memory mapped file, or executable and not writable, or (for modern systems) specially encrypted so that not even the kernel can access the data, or... This can/does extend to other characteristics beyond just access permissions ("use large pages", "disable caches for this area", ...).

b) The OS may (and I'd say should) provide a guarantee that memory the OS told you that you can use can actually be used. This requires the OS (e.g. sbrk(), mmap(), virtualAlloc(), ..) to be able to return an error condition to indicate that there isn't enough "physical RAM + swap" for the OS to guarantee that the space can actually be used. Without this guarantee processes unexpectedly crash and it becomes unacceptably difficult to write software that can recover gracefully (e.g. an extremely paranoid SIGSEGV signal handler that can't assume it can touch any memory, that can't be tested to see if it work properly under every possible set of conditions).

c) It significantly increases the chance of bugs being detected (e.g. dereferencing a dodgy/uninitialized pointer, array index out of bounds, etc), because they're more likely to correspond to an area that the OS wasn't explicitly asked to provide. This means it's significantly easier to find the root cause of the problem (e.g. easier to deal with "A caused B" than it is to deal with "A caused B, which caused C and that caused D"). Note that "bugs" includes hardware bugs (e.g. faulty RAM), compiler bugs, bugs in shared libraries and bugs in the OS - just because the symptoms appeared in your code doesn't necessarily mean your code is to blame.

Brendan
  • 35,656
  • 2
  • 39
  • 66