Segmentation in Linux : Segmentation & Paging are redundant? - operating-system

I'm reading "Understanding Linux Kernel". This is the snippet that explains how Linux uses Segmentation which I didn't understand.
Segmentation has been included in 80 x
86 microprocessors to encourage
programmers to split their
applications into logically related
entities, such as subroutines or
global and local data areas. However,
Linux uses segmentation in a very
limited way. In fact, segmentation
and paging are somewhat redundant,
because both can be used to separate
the physical address spaces of
processes: segmentation can assign a
different linear address space to each
process, while paging can map the same
linear address space into different
physical address spaces. Linux prefers
paging to segmentation for the
following reasons:
Memory management is simpler when all
processes use the same segment
register values that is, when they
share the same set of linear
addresses.
One of the design objectives of Linux
is portability to a wide range of
architectures; RISC architectures in
particular have limited support for
segmentation.
All Linux processes running in User
Mode use the same pair of segments to
address instructions and data. These
segments are called user code segment
and user data segment , respectively.
Similarly, all Linux processes running
in Kernel Mode use the same pair of
segments to address instructions and
data: they are called kernel code
segment and kernel data segment ,
respectively. Table 2-3 shows the
values of the Segment Descriptor
fields for these four crucial
segments.
I'm unable to understand 1st and last paragraph.

The 80x86 family of CPUs generate a real address by adding the contents of a CPU register called a segment register to that of the program counter. Thus by changing the segment register contents you can change the physical addresses that the program accesses. Paging does something similar by mapping the same virtual address to different real addresses. Linux using uses the latter - the segment registers for Linux processes will always have the same unchanging contents.

Segmentation and Paging are not at all redundant. The Linux OS fully incorporates demand paging, but it does not use memory segmentation. This gives all tasks a flat, linear, virtual address space of 32/64 bits.
Paging adds on another layer of abstraction to the memory address translation. With paging, linear memory addresses are mapped to pages of memory, instead of being translated directly to physical memory. Since pages can be swapped in and out of physical RAM, paging allows more memory to be allocated than what is physically available. Only pages that are being actively used need to be mapped into physical memory.
An alternative to page swapping is segment swapping, but it is generally much less efficient given that segments are usually larger than pages.
Segmentation of memory is a method of allocating multiple chunks of memory (per task) for different purposes and allowing those chunks to be protected from each other. In Linux a task's code, data, and stack sections are all mapped to a single segment of memory.
The 32-bit processors do not have a mode bit for disabling
segmentation, but the same effect can be achieved by mapping the
stack, code, and data spaces to the same range of linear addresses.
The 32-bit offsets used by 32-bit processor instructions can cover a
four-gigabyte linear address space.
Aditionally, the Intel documentation states:
A flat model without paging minimally requires a GDT with one code and
one data segment descriptor. A null descriptor in the first GDT entry
is also required. A flat model with paging may provide code and data
descriptors for supervisor mode and another set of code and data
descriptors for user mode
This is the reason for having a one pair of CS/DS for kernel privilege execution (ring 0), and one pair of CS/DS for user privilege execution (ring 3).
Summary: Segmentation provides a means to isolate and protect sections of memory. Paging provides a means to allocate more memory that what is physically available.

Windows uses the fs segment for local thread storage.
Therefore, wine has to use it, and the linux kernel needs to support it.

Modern operating systems (i.e. Linux, other Unixen, Windows NT, etc.) do not use the segmentation facility provided by the x86 processor. Instead, they use a flat 32 bit memory model. Each user mode process has it's own 32 bit virtual address space.
(Naturally the widths are expanded to 64 bits on x86_64 systems)

Intel first added segmentation on the 80286, and then paging on the 80386. Unix-like OSes typically use paging for virtual memory.
Anyway, since paging on x86 didn't support execute permissions until recently, OpenWall Linux used segmentation to provide non-executable stack regions, i.e. it set the code segment limit to a lower value than the other segment's limits, and did some emulation to support trampolines on the stack.

Related

Difference between paging and segmentation

I am trying to understand both paradigms of memory management;however, I fail to see the big picture and the difference between both. Paging consists of taking fixed size pages from a secondary to a primary storage in order to do some task requested by a process. Segmentation consists of assigning to each unit in a process an address space, so they are allowed to grow. I don't quiet see how they are related and that's because there are still a lot of holes in my understanding. Can someone fill them up?
I think you have something confused. One problem you have is that the term "segment" had multiple meanings.
Segmentation is a method of memory management. Memory is managed in segments that are of variable or fixed length, depending upon the processor. Segments originated on 16-bit processors as a means to access more than 64K of memory.
On the PDP-11, programmers used segments to map different memory into the 64K address space. At any given time a process could only access 64K of memory but the memory that made up that 64K could change.
The 8086 and it successors used segments with base registers. Each segment could have 64K (that grew with the processors) but a process could have 4 segments (more in later processors).
Paging allows a process to have a larger address space than there is physical memory available.
The 8086's successors used the kludge of paging on top of segments. However, that bit of ugliness has finally gone away in 64-bit mode.
You got your answer right there, paging relates with fixed size pages in a storage while segmentation deals with units in a page. 'Segments' are objects in the class 'Page'

Programmers and segmentation in operating systems

I'm learning that segmentation in operating systems is based on dividing different segments (for a program, these could represent a symbol table, the source text, the stack...) into units that start at logical memory address 0. This is the virtual address that the MMU (?) uses to get the real in addition to the offset.
An apparent benefit of segmentation is that, since each segment starts at address 0, multiple processes can take advantage of a single segment simultaneously (an example is the shared library).
However, I don't see how else segmentation can benefit programmers. What would be some examples?
Thanks!
Segmentation provides NO benefit to programmers. Segmentation is a kludge that developed to overcome architectural limits. The 16-bit PDP-11 computers could only address 64K of memory. The use of a segmentation allowed the programmer to map memory in and out of the address space to access more memory.
The 8086 chip was retrograde. IBM set the computer industry back by years using it for the PC rather than 68000. The 8086 used segments to reduce the size of instructions. Rather than using 32-bits for an address, instructions could use am offset from a segment register.
In 64-bit mode, the abomination of segments in the Intel processors finally goes away.

If only segmentation is enabled

beginners question:
"If" paging is disabled and only segmentation is enabled (CR0.PE is set) then does that mean if a program is loaded in memory (RAM), its whole binary image is loaded and none of its "part" is swapped out, becoz a program is broken into fixed size chunks only when paging is enabled (which then can be swapped out). And if it's true this will reduce the number of processes that run in memory of a particular size of RAM, say 2 GB?
Likely, but not necessarily.
It depends on the operating system...
You could write an operating system that uses a segment to map a part of the program into memory. When the program accesses memory outside the segment, you get a segmentation fault. As the segmentation fault is then passed to the operating system, it could swap in some data from disk and modify segmentation information, before returning control to the program.
However, this is probably difficult and expensive to do, and i do not know of any operating system that acts in this way.
As to the number of processes - you need to split the available memory into contiguous parts, one for each process. This is easy if processes do not grow; if they do, you need padding and may need to copy processes around, which is rather expensive...

Kernel high memory

In Operating System Design the kernel is most always mapped to a high virtual memory address, thus gaining control of the upper memory part. The space left below is for applications running in user space, as described in an excellent way in "Linux 3/1 virtual address split".
What I'd like to know is, why is this design decision made or why the kernel does not use the lower part of memory? This is not really clear to me, or maybe I've overseen something.
Edit: This question regards virtual addresses and not physical.
Some advantages of/reasons for such a design:
Applications don't need to care about the size and location of the kernel and may pretend they're the only ones in the memory, starting at around 0 and spanning upwards, with minimal or no code and data relocations. Applications are hence easier to design and implement and they may be less likely to have bugs related to mememory management.
Applications may use smaller/shorter addresses/pointers and hence save some memory.
In the x86 CPU, 16-bit and 32-bit address spaces start at virtual address 0 and end at around 1MB (for real and virtual 8086 modes), 16 MB (16-bit protected mode on i80286+) and 4 GB (32-bit mode, unreal mode). Placing the kernel at lower addresses will reduce the range of addresses available to applications (ex: 16-bit app in 32-bit mode or 32-bit app in 64-bit mode) and/or complicate their memory management. Moving the kernel to the top of the virtual address space generally makes sense on the x86.
There may be other reasons, usually platform-specific. On some platforms there may be little to no difference between the two options. Yet on others the preferred kernel location may be at the lower virtual addresses. Details matter.

Paging or segmentation for virtual memory, which is better?

Most OSes use paging for virtual memory. Why is this? Why not use segmentation? Is it just because of a hardware issue? Is one better than the other in certain cases? Basically, if you had to choose one over the other, which one would you want to use and why?
Let's assume it's an x86 for argument's sake.
OS like windows and Linux use a combination of both segmentation and paging. The virtual memory of a process is first divided into segments and then each segment consists of a lot of pages. The OS first goes to the specific segment and in that segment it then locates the particular page to access an address
Taken from :operating systems concepts by galvin
one of the issues..
Segmentation permits the physical address space of a process to be non-
contiguous. Paging is another memory-management scheme that offers this
advantage. However, paging avoids external fragmentation and the need for compaction, whereas segmentation does not.
Segmentaion problem:
The problem arises because, when code fragments
or data residing in main memory need to be swapped out, space must be found
on the backing store. The backing store has the same fragmentation problems
but access is much slower, so compaction is impossible.
Paging solves it by:
The basic method for implementing paging involves breaking physical memory into fixed-sized blocks called frames and breaking logical memory into
blocks of the same size called pages.The backing store is divided into fixed-sized blocks that are the same size as the memory frames or clusters of multiple frames.
Since pages-frames-The backing store all are divided into same size so it doesn't lead to external fragmentation. But may have internal fragmentation.
So pagesize must be chosen correctly
Operating Systems concepts
Note, that Single-Address-Space Operating Systems sometimes use segmentation to isolate processes.