11

Minix, as most know, is a "Unix-like" OS originally used for teaching. Early Minix (v1 and, apparently, v2) ran on the 8088/6 series of processors. It could run on the IBM XT.

There have been several discussions about UNIX style OSes and their reliance on a Memory Management Unit, for a variety of reasons.

But the 8086 did not have a built in MMU, nor did the XT have any kind of external MMU functionality.

So, the question is how did early Minix manage its processes? I've looked at some artifacts on the web about Minix 1, but when they discuss processes, they don't go in to the problems of actually loading code in to RAM and executing it. I've posited elsewhere that they could be using Intel Tiny model programs, which would provide some modicum of safety to programs written in something like C, but it would mandate a 64k memory segment. Which was quite expensive when Minix originally came out.

I know that modern Minix is a "micro-kernel" with many of the OS services running in User Space as processes, I don't know if that's the case with Minix 1 or 2. If it was, then it makes the 64k memory limit even more demanding because of the many user processes that a micro-kernel design has that normally reside in the monolithic kernel. A file system is a complicated beast, but it certainly doesn't require 64k of RAM, especially the early ones.

There are all sorts of things that could have been done, I'm just curious if anyone actually knows how Minix managed this.

9
  • 5
    Memory Management != Address Translation != Memory Protection, despite that all three are nowadays often seen as bundled, as hardware MMUs (may) deliver all three at once. And memory management is just about assigning memory to processes, when they need some. This can quite well be done without any hardware (like DOS 360, classic Mac OS or OS/9 did). In fact, the 8086 is quite enabled for memory management and address translation due its segmented nature.
    – Raffzahn
    Jan 7, 2022 at 21:38
  • Yes, of course, @Raffzahn but that doesn't address the question. There are all sorts of techniques and tricks and leveraging of architectures. This isn't about that, it's about how did early Minix specifically answer those questions. Jan 7, 2022 at 21:44
  • 4
    I don't know the answer, but I'm pretty sure it's in the 1st edition of Tanenbaum & Woodhull, Operating Systems, Design and Implementation., Minix pretty much being the companion OS to Tanenbaum's teaching. Have you checked? Jan 7, 2022 at 22:06
  • True. But that's exactly the point here. Minix 3 (before 3.2) had all memory management done within the PM server. Processes had text and heap. Heap holds data, bss and stack. programs can be either compiled for on single I+D segment (tiny) or I/D separated (small). Tiny was default up to 2.0. Segments are only as large as need and continous (not partitioned), and either all segments were swapped in or not (swapping was optional, not all systems used it). Text may be shared. No protection of any kind. 3.2 added VM server, memory management was moved from PM to VM.
    – Raffzahn
    Jan 7, 2022 at 22:06
  • 2
    Basic Minix did not allow any resizing. IIRC it could be added as a server. Memory allocation within a process was restricted to whatever the file contained plus the required heap as marked. The heap amount could be changed with the CHMEM command. It could not go past 64 KiB for (Text+)Data+BSS+Heap+Stack. (or should, no idea if there that was checked at all).
    – Raffzahn
    Jan 7, 2022 at 22:24

1 Answer 1

11

[Edit: Found a page about the Minix 3 PM supporting my memory.]


Backgound

When looking from today's perspective back, it's always important to as well look at usage of terms. 'MMU' and Memory Management are used interchangeable and most automatically include Address Translation and Memory Protection (often as well Paging). But that's a false shortcut based on modern hardware MMU providing all three (four) aspects at once.

Memory Management != Address Translation != Memory Protection

Memory management is strictly only assigning memory to processes, when they need some. Static or dynamic, whatever a system provides. This can quite well be done without any hardware (like DOS 360, classic Mac OS or OS/9 did). In fact, the segmented nature of the 8086 is quite supportive of memory management, providing basic address translation, eliminating all need for relocation (*1).


How Minix implemented it:

(this is about 8086, but AFAIK the basic working were the same for 80386, 68k and SPARC)

Minix 3 (before 3.2) had all memory management done within the PM server. The program map of a process after loading structured the segments as (low to high):

(It's important to note that this is about logical segments of a program, not 8086 segments)

  • Text (Code)
  • Data
  • BSS
  • Heap
  • Stack

Of these only

  • Text, holding the program code,
  • Data, holding all predefined data (including BSS) and
  • Stack (I'm not sure about this)

were part of the program file. All others were generated from values of the program header (a.out). The amount of heap needed was calculated from the total memory requirement value.

When loading a program, a memory block was searched with a size to hold all file content (text+data) plus stack plus heap. All these logical segments were put into a single 8086 segment, with CS=DS(=ES)=SS pointing to it. In Intel terminology the Tiny memory model. This was the default compile for all 8086 Minix up to 3.0.

In addition programs could be compiled with separation between text and data (Instruction and Data in Minix terms). In this case two 8086 segments were allocated, one for the code portion of a program file, the other for all remaining parts. In Intel speak that's the Small memory model. Small was made default with Minix 3.0

Segments in memory are only as large as they needed to be (usually smaller than 64 KiB) and continuous (not partitioned). If there is a separate Instruction segment (Small model), it may be shared. Swapping was done either in whole or not at all (there was a special case for shared code). Swapping was optional, not all systems used it - which is true for most 8086 Minix.

Minix 3.2 added a VM server and memory management was in turn moved from PM to VM.

There was no protection of any kind.

Any program using

  • a pointer past its allocated 8086 segment(s), or
  • changed the 8086 segment register value

was able to access and manipulate arbitrary memory, including the OS or its servers.


But what if a program needs more memory?

Bad luck. Basic Minix did not allow any resizing.

When a process is requesting more memory, it's taken, bottom up, from the prior assigned Heap. The only check made is against the lower boundary of the stack. If a requested amount would cross into the stack segment, the call will fail.

Memory allocation within a process is thus restricted to whatever amount of Heap was reserved via the header value. The amount could be changed with the CHMEM command. It could not go past 64 KiB for (Text+)Data+BSS+Heap+Stack (or should, no idea if there that was checked at all).


Why?

Minix is a teaching tool, not a productive environment. It's all about showing how things work, not building a system surviving evil code. Doing such will add many bells and whistles that would make it hard to see the core functionality.

This is as well the reason why Minix didn't care to provide larger segments, or more than 1(2) segments. The addition of the Small memory model was only made to show ability and workings of shared code as a tool to save on memory - something way more important back in the days. Well and to introduce all the litte tripwires this included :)

In fact, it's the basic idea of Minix' micro kernel structure that only a bare minimum is provided. Additional features are to be added as services.


*1 - If Stephen Morse had added segment size registers and a basic supervisor mode, the 8086 would have had everything to run a segmented protected mode OS. Essentially the only serious shortfall one could attribute to the 8086 design.

2
  • 2
    Thanks Raffzahn, that's what I wanted to know. Many systems used a header value to specify heap size. The segment system along with the tiny/small models avoid the need of a relocating loader (the IIGS uses a loader, for example), or requiring PIC code (which I don't know how viable is with the x86 anyway). Protection isn't necessary for something like Minix or for single user systems (Win 3, MacOS, IIGS). Frustrating, but not a crisis. One thing to lose your own work, quite another to lose someone else's. Jan 7, 2022 at 23:55
  • 3
    @WillHartung Well, nor does Minix on the 8086 need relocation. 8086 programs are inherently relocatable as all addressing in tiny/small memory model does not need any relocation. All those values are part of the Minx A.Out format
    – Raffzahn
    Jan 8, 2022 at 0:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .