Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am studying operating systems and the x86 architecture, and while I was reading about segmentation and paging I naturally was curious how modern OSes handle memory management. From what I found Linux and most other operating systems essentially shun segmentation in favor of paging. A few of the reasons for this that I found were simplicity and portability.

What practical uses are there for segmentation (x86 or otherwise) and will we ever see robust operating systems using it or will they continue to favor a paging based system.

Now I know this is a loaded question but I am curious how segmentation would be handled with newly developed operating systems. Does it make so much sense to favor paging that no one will consider a more 'segmented' approach? If so, why?


And when I say 'shun' segmentation I am implying that Linux only uses it as far as it has to. Only 4 segments for user and kernel code/data segments. While reading the Intel documentation I just got the feeling that segmentation was designed with more robust solutions in mind. Then again I was told on many occasions how over complicated the x86 can be.


I found this interesting anecdote after being linked to Linux Torvald's original 'announcement' for Linux. He said this a few posts later:

Simply, I'd say that porting is impossible. It's mostly in C, but most people wouldn't call what I write C. It uses every conceivable feature of the 386 I could find, as it was also a project to teach me about the 386. As already mentioned, it uses a MMU, for both paging (not to disk yet) and segmentation. It's the segmentation that makes it REALLY 386 dependent (every task has a 64Mb segment for code & data - max 64 tasks in 4Gb. Anybody who needs more than 64Mb/task - tough cookies).

I guess my own experimentation with x86 led me to ask this question. Linus didn't have StackOverflow, so he just implemented it to try it out.

share|improve this question

migrated from stackoverflow.com Aug 10 '11 at 18:54

This question came from our site for professional and enthusiast programmers.

    
What book did you read? –  osgx Aug 10 '11 at 14:23
1  
I am reading a number of books. I started to ask myself this while reading the Intel Systems Programming manual (vol 3), but I read a little about Linux memory management in "Understanding the Linux Kernel" and other sources online. –  Mr. Shickadance Aug 10 '11 at 14:25
    
In particular I was reading the section on Local Descriptor Tables, and I was curious how operating systems used these. –  Mr. Shickadance Aug 10 '11 at 14:32
1  
OpenBSD combines x86 segmentation and paging to get NX bit simulation (security feature to prohibit execution of data pages). May be PaX used this too. –  osgx Aug 10 '11 at 14:33
    
I know next to nothing on the subject. I just typed in a search question to see answers for complaints about all currently used operating systems. Looking at the complaints, most people use pc's and now tablets for a few specific tasks. So why not allocate more memory usage to do those tasks quicker as opposed to giving all of the peripheral crap that is running access to it. –  user97211 Jul 20 '13 at 3:08

5 Answers 5

The short answer is that segmentation is a hack, used to make a processor with a limited ability to address memory exceed those limits.

In the case of the 8086, there were 20 address lines on the chip, meaning that it could physically access 1Mb of memory. However, the internal architecture was based around 16 bit addressing, probably due to the desire to retain consistency with the 8080. So the instruction set included segment registers that would be combined with the 16-bit indexes to allow addressing of the full 1Mb of memory. The 80286 extended this model with a true MMU, to support segment-based protection and addressing of more memory (iirc, 16Mb).

In the case of the PDP-11, later models of the processor provided a segmentation into Instruction and Data spaces, again to support the limitations of a 16-bit address space.

The problem with segmentation is simple: your program must explicitly work around the limitations of the architecture. In the case of the 8086, this meant that the largest contiguous block of memory that you could access was 64k. if you needed to access more than that, you would have to change your segment registers. Which meant, for a C programmer, that you had to tell the C compiler what sort of pointers it should generate.

It was a lot easier to program the MC68k, which had a 32-bit internal architecture and a 24-bit physical address space.

share|improve this answer
3  
Ok, that all makes sense. However, reading the Intel documents one would be inclined to think segments could actually be used for greater hardware level protection against program bugs. Specifically section 3.2.3 of the Systems Programming Guide - are there advantages to the multi-segment model? Would it be correct to say Linux uses the protected flat model? (section 3.2.2) –  Mr. Shickadance Aug 10 '11 at 17:22
2  
It's been a long time since I paid attention to the details of the Intel memory architecture, but I don't think that the segmented architecture would provide any greater hardware protection. The only real protection that an MMU can give you is to separate code and data, preventing buffer overrun attacks. And I believe that's controllable without segments, via page-level attributes. You could theoretically restrict access to objects by creating a separate segment for each, but I don't think that's reasonable. –  parsifal Aug 10 '11 at 17:37
    
This all makes sense. From my experience its quite easy to ask yourself 'Why?' when reading the Intel manuals. I'm just going to leave this open a bit before accepting this answer to perhaps get more perspective. Thanks! –  Mr. Shickadance Aug 10 '11 at 17:56
1  
Thanks, you have brought back all the repressed memories of doing image processing on segmented memory - this is going to mean more therapy! –  Martin Beckett Aug 10 '11 at 19:15
2  
You have completely misunderstood the segmentation. In 8086 it might have been a hack; 80286 introduced protected mode where it was crucial for protection; in 80386 it was even further extended and segments can be larger than 64kB, still with the benefit of hardware checks. (BTW, 80286 did NOT have an MMU.) –  zvrba Aug 11 '11 at 9:59

With segmentation it would be, for example, possible to put each dynamically allocated object (malloc) in its own memory segment. Hardware would check segment limits automatically, and the whole class of security bugs (buffer overruns) would be eliminated.

Also, since all segment offsets start at zero, all compiled code would automatically be position independent. Calling into another DLL would boil down to a far call with constant offset (depending on the called function). This would greatly simplify linkers and loaders.

With 4 protection rings, it is possible to devise more fine-grained access control (with paging you have only 2 protection levels: user and supervisor) and more robust OS kernels. For example, only ring 0 has full access to the hardware. By separating the core OS kernel and device drivers into rings 0 and 1, you could make a more robust and very fast microkernel OS where most of the relevant access checks would be done by HW. (Device drivers could get access to hardware through I/O access bitmap in the TSS.)

However.. x86 is a bit limited. It has only 4 "free" data segment registers; reloading them is rather expensive, and it is possible to simultaneously access only 8192 segments. (Assuming you want to maximize the number of accessible objects, so the GDT holds only system descriptors and LDT descriptors.)

Now, with 64-bit mode segmentation is described as "legacy" and hardware limit checks are done only in limited circumstances. IMHO, a BIG mistake. Actually I don't blame Intel, I mostly blame developers, the majority of which thought that segmentation was "too complicated" and longed for flat address space. I also blame the OS writers who lacked the imagination to put segmentation to good use. (AFAIK, OS/2 was the only operating system which made full use of segmentation features.)

share|improve this answer
1  
This is why I left this opened. There is sure to be a few different takes on the issue... –  Mr. Shickadance Aug 11 '11 at 16:42

Segmentation was a hack / workaround to allow up to 1MB of memory to be addressed by a 16 bit processor - normally only 64K of memory would have been accessible.

When 32 bit processors came along you could address up to 4GB of memory with a flat memory model and there was no longer any need for segmentation - The segment registers were re-purposed as selectors for the GDT / paging in protected mode (although you can have protected mode 16-bit).

Also a flat memory mode is far more convenient for compilers - you can write 16-bit segmented programs in C, but its a tad cumbersome. A flat memory model makes everything simpler.

share|improve this answer
    
Is there much to be said of the 'protection' provided by segmentation when we can just use paging instead? –  Mr. Shickadance Aug 10 '11 at 17:35
1  
@Mr. Shickadance Segmentation doesn't provide any sort of memory protection - For memory protection you need protected mode where you can protect memory using either the GDT or paging. –  Justin Aug 11 '11 at 8:13

For 80x86 there are 4 options - "nothing", segmentation only, paging only, and both segmentation and paging.

For "nothing" (no segmentation or paging) you end up with no easy way to protect a process from itself, no easy way to protect processes from each other, no way to handle things like physical address space fragmentation, no way to avoid position independent code, etc. Despite all these problems it might (in theory) be useful in some situations (e.g. embedded device that only runs one application; or maybe something that uses JIT and virtualises everything anyway).

For segmentation only; it almost solves the "protect a process from itself" problem, but it takes a lot of work-arounds to make it usable when a process wants to use more than 8192 segments (assuming one LDT per process), which makes it mostly broken. You almost solve the "protect processes from each other" problem; but different pieces of software running at the same privilege level can load/use each other's segments (there's ways to work around that - modifying GDT entries during control transfers and/or using LDTs). It also mostly solves the "position independent code" problem (it can cause a "segment dependant code" problem but that's much less significant). It doesn't do anything for the "physical address space fragmentation" problem.

For paging only; it doesn't solve the "protect a process from itself" problem much (but let's be honest here, this is only really a problem for debugging/testing code written in unsafe languages, and there's much more powerful tools like valgrind anyway). It completely solves the "protect processes from each other" problem, completely solves the "position independent code" problem, and completely solves the "physical address space fragmentation" problem. As an added bonus it opens up some very powerful techniques that aren't anywhere near as practical without paging; including things like "copy on write", memory mapped files, efficient swap space handling, etc.

Now you'd think that using both segmentation and paging would give you the benefits of both; and in theory it can, except that the only benefit you gain from segmentation (that isn't done better by paging) is a solution to the "protect a process from itself" problem that nobody really cares about. In practice what you do get is the complexities of both and the overhead of both, for very little benefit.

This is why almost all OSs designed for 80x86 don't use segmentation for memory management (they do use it for things like per-CPU and per-task storage but that's mostly just for convenience to avoid consuming a more useful general purpose register for these things).

Of course CPU manufacturers aren't silly - they aren't going to spend time and money optimising something that they know nobody uses (they're going to optimise something that almost everyone uses instead). For this reason CPU manufacturers don't optimise segmentation, which makes segmentation slower than it could be, which makes OS developers want to avoid it even more. Mostly they only kept segmentation for backward compatibility (which is important).

Eventually, AMD designed long mode. There was no old/existing 64 bit code to worry, so (for 64-bit code) AMD got rid of as much segmentation as they could. This gave OS developers yet another reason (no easy way to port code designed for segmentation to 64-bit) to continue avoiding segmentation.

share|improve this answer

Segmentation is a huge burden for applications developers. This is where the big push came from to do away segmentation.

Interestingly I often wonder how much better i86 could be if Intel striped out all legacy support for these old modes. Here better would imply lower power and maybe faster operation.

I guess one could argue that Intel soured the milk with 16bit segments leading to a developer revolt of sorts. But let's face it a 64k address space is nothing especially when you look at modern app. In the end they had to do something because the competition could and did market effectively against the address space issues of i86.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.