Why The Virtual Memory (VM)

Why The Virtual Memory (VM)

History in short

In 1979 was implemented the 3BSD by researchers at Berkeley. That was the first Unix release with virtual memory.

In 1992 the virtual memory introduction turn was for Microsoft and its Windows NT.

In 2002 Apple began the implementation of virtual memory when moving from OS 9 to OS X operating system for MAC.

This information tells us about virtual memory as an important idea. The question is why?

The main problem that conducts to the Virtual Memory (VM), was the resource optimization for the time-sharing processing to support multitasking and multi-user operating systems.

The idea is creating logical spaces of memory and backing it with real physical memory coordinated according to a set of mapping tables created and maintained dynamically.

Specifically, the reasons are:

  • The OS processes only can see a dedicated logical space of memory each.
  • An operating system process cannot interfere with others.
  • The sparse memory layout is handled efficiently.
  • Processes can share programs and data.
  • Efficiency can be gained by creating a memory hierarchy.

The context

If you need to compute two simple values by addition you can easily store both values in your brain and calculate de result that is put into your brain too but, if you need to compute complex values you will need to store that values in an external media. And, it can be typically paper. Then, you do different simple calculus partially written on the paper and as an outcome. Therefore, we can get the final result. Here we can see two important things.

  • When data is simple, the process is simple and the storage is simple
  • When data is complex, the process is complex and the storage is complex

This is the point: A computer has to solve these kinds of problems too and face their complexity. In memory case, the answer is Virtual Memory (VM).

What keeps in mind about storage and memory?

Computer data storage is a technology consisting of computer components and recording media that are used to retain digital data.

The storage hierarchy lets the central processing unit (CPU) performs computations with data. Usually, the storage hierarchy is organized in levels according to its cost and performance puts fast and expensive hardware close to the CPU and less expensive but slower hardware further away. Generally, the faster are volatile and known as “memory” and the slower are persistent and are known as “storage”

No alt text provided for this image

Above we have three levels of computer data storage. Let’s see them:

Primary storage

It is the level the CPU directly access to compute and it is known as main memory or simply as memory. The primary storage has processor registers that are ultra-fasts, processor cache as speed up element between ultra-fast processor registers, and main memory. The RAM memory is implanted on integrated circuit technology. This technology allows semiconductor memory an acceptable trade-off and it is economically competitive

Secondary storage

The main difference with primary memory is the secondary is not accessible directly by the CPU. Thus the system buses are used to move data from secondary storage to the primary. The clue here is the secondary memory is nonvolatile. The most common devices in this kind of storage are the hard disk drives (HDD) and the solid-state drives (SDD).

Tertiary storage

This memory level is for archiving information that is rarely accessed. It is common that these devices use robotic mechanisms to mount or dismount the mass storage media. The most common devices to this category are tape or optic-disk libraries.

Off-line storage

When a storage device is not under the control of the CPU we can say it is off-line storage. These are secondary or tertiary tier memory devices and are removable or pluggable.

Virtual Memory at MMU

No alt text provided for this image

The memory management unit (MMU), is a small device located between CPU and RAM having all memory references passed through itself and get the actual memory address. Therefore, it performs the translation of virtual memory addresses to physical addresses. This is a hardware solution for Virtual Memory (VM) and uses the translation lookaside buffer (TLB) to do it.

Virtual Memory and HSA

A Heterogeneous System Architecture (HSA) is a set of specifications that integrates the central processing units (CPU), and graphics processors (GPU) on the same bus, with shared memory and tasks. This is a cross-vendor solution and, it is supported by AMD and ARM among many others. System-on-chip devices such as tablets, smartphones, other mobile devices, and video game consoles are implanted widely with heterogeneous computing (HSA).

No alt text provided for this image

System with HAS

No alt text provided for this image

System with HSA

Virtual Memory as a wider concept

No alt text provided for this image

Previous we talked about VM in hardware but the concept can be implanted in software too just as part of the Operating system consequently, the VM can expand its capacity further the memory boundaries.

And, this wider approach allows the operating system to addresses:

Easy managing

The physical space must be shared, and it might be shared in some very messy ways. However, the physical memory is not seen by the process, only the virtual memory. The logical view is typically a linear array of byte numbers 0, 1, 2, etc., to the maximum location number.

Let’s see:

vagrant@gogomillan:~$ rev &
[1] 27363
vagrant@gogomillan:~/try$ ps
  PID TTY          TIME CMD
22711 pts/2    00:00:04 bash
27363 pts/2    00:00:00 rev
27364 pts/2    00:00:00 ps 

[1]+  Stopped                 rev
vagrant@gogomillan:~$

---

vagrant@gogomillan:~$ cat /proc/27363/maps
00400000-00402000 r-xp 00000000 08:01 55383                              /usr/bin/rev
00601000-00602000 r--p 00001000 08:01 55383                              /usr/bin/rev
00602000-00603000 rw-p 00002000 08:01 55383                              /usr/bin/rev
0220e000-0222f000 rw-p 00000000 00:00 0                                  [heap]
7fbd149b4000-7fbd14b72000 r-xp 00000000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
...
7fbd14fa0000-7fbd14fa1000 rw-p 00023000 08:01 2188                       /lib/x86_64-linux-gnu/ld-2.19.so
7fbd14fa1000-7fbd14fa2000 rw-p 00000000 00:00 0
7ffecfa8a000-7ffecfaab000 rw-p 00000000 00:00 0                          [stack]
7ffecfbdd000-7ffecfbdf000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
vagrant@gogomillan:~$
vagrant@gogomillan:~$ sudo ./pagemap 27363 0x0400000
Big endian? 0
Vaddr: 0x400000, Page_size: 4096, Entry_size: 8
Reading /proc/27363/pagemap at 0x2000
[0]0xf9 [1]0xf8 [2]0x3 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa60000000003f8f9
PFN: 0x3f8f9
vagrant@gogomillan:~$

The previous example was running the “rev” command, the VM shows 0x0400000 as the memory address and the “Result” is 0x03F8F9 as the physical. Now let’s see with another:

vagrant@gogomillan:~$ cat - &
[1] 27506
vagrant@gogomillan:~$ ps
  PID TTY          TIME CMD
22711 pts/2    00:00:05 bash
27506 pts/2    00:00:00 cat
27507 pts/2    00:00:00 ps
[1]+  Stopped                 cat -
vagrant@gogomillan:~$ cat /proc/27506/maps
00400000-0040b000 r-xp 00000000 08:01 129                                /bin/cat
0060a000-0060b000 r--p 0000a000 08:01 129                                /bin/cat
0060b000-0060c000 rw-p 0000b000 08:01 129                                /bin/cat
00a13000-00a34000 rw-p 00000000 00:00 0                                  [heap]
7fd76f8c0000-7fd76fa7e000 r-xp 00000000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
...
7fd76feac000-7fd76fead000 rw-p 00023000 08:01 2188                       /lib/x86_64-linux-gnu/ld-2.19.so
7fd76fead000-7fd76feae000 rw-p 00000000 00:00 0
7ffd9661a000-7ffd9663b000 rw-p 00000000 00:00 0                          [stack]
7ffd966fd000-7ffd966ff000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
vagrant@gogomillan:~$
vagrant@gogomillan:~$ sudo ./pagemap 27506 0x0400000
Big endian? 0
Vaddr: 0x400000, Page_size: 4096, Entry_size: 8
Reading /proc/27506/pagemap at 0x2000
[0]0x9b [1]0xf8 [2]0x3 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa60000000003f89b
PFN: 0x3f89b
vagrant@gogomillan:~$

The previous example was running the “rev” command, the VM shows 0x0400000 as the memory address and the “Result” is 0x03F89B as the physical. As we can see the VM is the same for both process hiding as a convenient fact the physical address.

To identify this data you need the privilege and access to the proc(5) file-system, particularly the maps and pagemap files.

Protected and secure

Unless the mapping tables have mapped the same physical memory into both processes’ virtual memory, the processes cannot affect each other’s memory. Even a crashing or badly misbehaving program cannot affect memory that is not mapped into its space

Let’s see:

vagrant@gogomillan:~$ cat - &
[1] 27825
vagrant@gogomillan:~$ ps
  PID TTY          TIME CMD
22711 pts/2    00:00:05 bash
27825 pts/2    00:00:00 cat
27826 pts/2    00:00:00 ps
[1]+  Stopped                 cat -
vagrant@gogomillan:~$ cat - &
[2] 27828
vagrant@gogomillan:~$ ps
  PID TTY          TIME CMD
22711 pts/2    00:00:05 bash
27825 pts/2    00:00:00 cat
27828 pts/2    00:00:00 cat
27829 pts/2    00:00:00 ps

[2]+  Stopped                 cat -


--

vagrant@gogomillan:~$ cat /proc/27825/maps | head -1
00400000-0040b000 r-xp 00000000 08:01 129                                /bin/cat
vagrant@vagrant-ubuntu-trusty-64:~/try$ cat /proc/27828/maps | head -1
00400000-0040b000 r-xp 00000000 08:01 129                                /bin/cat
vagrant@gogomillan:~$
vagrant@gogomillan:~$ sudo ./pagemap 27825 0x0400000
Big endian? 0
Vaddr: 0x400000, Page_size: 4096, Entry_size: 8
Reading /proc/27825/pagemap at 0x2000
[0]0x9b [1]0xf8 [2]0x3 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa60000000003f89b
PFN: 0x3f89b
vagrant@gogomillan:~$ sudo ./pagemap 27828 0x0400000
Big endian? 0
Vaddr: 0x400000, Page_size: 4096, Entry_size: 8
Reading /proc/27828/pagemap at 0x2000
[0]0x9b [1]0xf8 [2]0x3 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa60000000003f89b
PFN: 0x3f89b
vagrant@gogomillan:~$

The above example shows us a “cat” command executed twice therefore we have two processes but the VM of both points to the same physical memory (0x03F89B). That’s because it is the same binary from the disc and the OS can save memory putting only one copy in memory and the processes have their pointers to the same memory page through the VM.

Optimizing limited resources

There are situations where it is convenient to layout memory usages including large gaps of unused memory. A good example is the gap between the top of the heap and the bottom of the stack is largely unused, the amount unused is not known until runtime as the stack and heap grow towards each other. By not mapping the memory in this gap, space does not consume physical memory, given that it doesn't need any physical memory, and that resource can be used elsewhere.

Let’s see:

vagrant@gogomillan:~$ cat /proc/27828/maps
00400000-0040b000 r-xp 00000000 08:01 129                                /bin/cat
0060a000-0060b000 r--p 0000a000 08:01 129                                /bin/cat
0060b000-0060c000 rw-p 0000b000 08:01 129                                /bin/cat
0133c000-0135d000 rw-p 00000000 00:00 0                                  [heap]
7f592ebb5000-7f592ed73000 r-xp 00000000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
7f592ed73000-7f592ef73000 ---p 001be000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
7f592ef73000-7f592ef77000 r--p 001be000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
7f592ef77000-7f592ef79000 rw-p 001c2000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
7f592ef79000-7f592ef7e000 rw-p 00000000 00:00 0
7f592ef7e000-7f592efa1000 r-xp 00000000 08:01 2188                       /lib/x86_64-linux-gnu/ld-2.19.so
7f592f00c000-7f592f195000 r--p 00000000 08:01 54941                      /usr/lib/locale/locale-archive
7f592f195000-7f592f198000 rw-p 00000000 00:00 0
7f592f1a0000-7f592f1a1000 r--p 00022000 08:01 2188                       /lib/x86_64-linux-gnu/ld-2.19.so
7f592f1a1000-7f592f1a2000 rw-p 00023000 08:01 2188                       /lib/x86_64-linux-gnu/ld-2.19.so
7f592f1a2000-7f592f1a3000 rw-p 00000000 00:00 0
7ffcfafb5000-7ffcfafd6000 rw-p 00000000 00:00 0                          [stack]
7ffcfafe6000-7ffcfafe8000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  
[vsyscall]
vagrant@gogomillan:~$

The memory layout for the previous cat process has a big memory space between the heap and the stack with only a few segments used. Because these segments in the memory are continuous let the operating system optimize the resources.

No alt text provided for this image

Leveraging by synergy

By mapping the same physical memory into multiple processes, the memory is shared. This is particularly useful for code libraries, which can be put into physical memory only once, and then used by any process that needs the library by mapping the physical memory into the process' logical space.

Let’s see:

vagrant@gogomillan:~/try$ ps
  PID TTY          TIME CMD
22711 pts/2    00:00:05 bash
27825 pts/2    00:00:00 cat
27973 pts/2    00:00:00 rev
27976 pts/2    00:00:00 ps
vagrant@gogomillan:~/try$ cat /proc/27825/maps
00400000-0040b000 r-xp 00000000 08:01 129                                /bin/cat
0060a000-0060b000 r--p 0000a000 08:01 129                                /bin/cat
0060b000-0060c000 rw-p 0000b000 08:01 129                                /bin/cat
00836000-00857000 rw-p 00000000 00:00 0                                  [heap]
7fda29af6000-7fda29cb4000 r-xp 00000000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
...
vagrant@gogomillan:~/try$ cat /proc/27973/maps
00400000-00402000 r-xp 00000000 08:01 55383                              /usr/bin/rev
00601000-00602000 r--p 00001000 08:01 55383                              /usr/bin/rev
00602000-00603000 rw-p 00002000 08:01 55383                              /usr/bin/rev
00f42000-00f63000 rw-p 00000000 00:00 0                                  [heap]
7f3ec31ec000-7f3ec33aa000 r-xp 00000000 08:01 2077                       /lib/x86_64-linux-gnu/libc-2.19.so
...
vagrant@gogomillan:~/try$

--

vagrant@gogomillan:~/try$ sudo ./pagemap 27825 0x7fda29af6000
Big endian? 0
Vaddr: 0x7fda29af6000, Page_size: 4096, Entry_size: 8
Reading /proc/27825/pagemap at 0x3fed14d7b0
[0]0xd1 [1]0x1a [2]0x2 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa600000000021ad1
PFN: 0x21ad1
vagrant@gogomillan:~/try$ sudo ./pagemap 27973 0x7f3ec31ec000
Big endian? 0
Vaddr: 0x7f3ec31ec000, Page_size: 4096, Entry_size: 8
Reading /proc/27973/pagemap at 0x3f9f618f60
[0]0xd1 [1]0x1a [2]0x2 [3]0x0 [4]0x0 [5]0x0 [6]0x0 [7]0xa6
Result: 0xa600000000021ad1
PFN: 0x21ad1
vagrant@gogomillan:~/try$

As we can see in the above example “cat” and “rev” both commands use the “libc-2.19.so” library. Accordingly, the Operating System create different VM addresses (0x7FDA29AF6000 and 0x7f3EC31EC000) but mapping to the same physical memory address (0x021AD1).

Gaining efficiency

The physical memory can be either RAM which is fast and expensive or disk which is slow but plentiful. Virtual locations that "go cold", that is, that contain code or data which is not now being used, are stored on disk. As the locations become "hot", the disk data is copied into RAM. This allows better use of resources and allows more programs to run well on a machine. The storage area on the disk can be a dedicated location called swap space. For code, the source file itself is used.

Let’s see:

No alt text provided for this image

Virtual memory and shared memory

Previously we see that multiple virtual memory spaces can be mapped to the same physical page. Among others, we can use this to communicate processes. This functionality is provided from operating system calls. One of these is shmat (Shared Memory Attach). The memory need not map to the same address. Shared memory can quickly fork child processes but marking writable pages as copy-on-write. The fork will no create a clone, but simply set up new page tables, copies of the original page tables. This way the child process starts quickly, and only copies what is needed so that both processes see the own image of the memory.

A good example is a database cache structure the Oracle Database Management System implants. Let’s see:

SQL> STARTUP
ORACLE instance started.

Total System Global Area  619360256 bytes
Fixed Size                  1338280 bytes
Variable Size             377488472 bytes
Database Buffers          234881024 bytes
Redo Buffers                5652480 bytes
Database mounted.
Database opened.

The above sentence create shared Memory segments available to processes through the VM. Let’s continue:

vagrant@gogomez:~$ ipcs -a
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0xc616cc44 1056800768 oracle    660        619360256 0
0x0103f577 323158020  root      664        966        1
0x0000270f 325713925  root      666        1          2

------ Semaphore Arrays --------
key        semid      owner      perms      nsems
0x0103eefd 0          root      664        1
0x0103eefe 32769      root      664        1
0x4b0d4514 1094844418 oracle    660        204

------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
0x000005a4 32768      root       644        0            0

We can see as the shared segments are addressable and are coordinated with semaphores.

 The /proc data structure

We can see the documentation about proc(5) to identify that exists a structure to map the VM to physical memory. Nowadays that is a privileged structure.

/proc/[pid]/pagemap (since Linux 2.6.25)

This file shows the mapping of each of the process's virtual pages into physical page frames or swap area. It contains one 64-bit value for each virtual page, with the bits set as follows:

  •  63    If set, the page is present in RAM.
  • 62    If set, the page is in swap space
  • 61 (since Linux 3.5) The page is a file-mapped page or a shared anonymous page.
  • 60–57 (since Linux 3.11) Zero
  • 56 (since Linux 4.2) The page is exclusively mapped.
  • 55 (since Linux 3.11) PTE is soft-dirty (see the kernel source file Documentation/adminguide/mm/soft-dirty.rst).
  • 54–0  If the page is present in RAM (bit 63), then these bits provide the page frame number, which can be used to index /proc/kpageflags and /proc/kpagecount. If the page is present in the swap (bit 62), then bits 4–0 give the swap type, and bits 54–5 encode the swap offset.

Further information (https://www.kernel.org/doc/Documentation/vm/pagemap.txt)

Summary

As a summary, we can understand the Virtual Memory is an architectural component for hardware systems and operating systems. The concepts behind are resource optimization, security, and intercommunication. Without VM architecture the modern systems could not be cost-efficient.

References

Kernel.org - (pagemap)

Linux man - proc(5), malloc(3), ipcs(1)

Wikipedia (Virtual Memory)


要查看或添加评论,请登录

Gonzalo Gomez Millan的更多文章

  • Linux, ELF, and Hacking!

    Linux, ELF, and Hacking!

    What is ELF? The Executable and Linkable Format, otherwise called ELF, is the nonexclusive document design for…

  • Hacking The Linux Kernel

    Hacking The Linux Kernel

    Linux architecture has a lot of relevant pieces that allow it to work flexibly and powerfully. The file system /proc is…

  • Voici d'emploi - Job posting on third platforms (Torre.co)

    Voici d'emploi - Job posting on third platforms (Torre.co)

    Our project helps people solve a critical problem: find a job. In this case, is through making viral on the internet…

  • Post-incident analysis

    Post-incident analysis

    A new functional requirement that was developed without doing an impact analysis on the architecture. Issue summary As…

  • Internet of things as a day-to-day story

    Internet of things as a day-to-day story

    It was 1999. Kevin Ashton worked for Procter & Gamble (P&G), and was 28 years old and tried to solve a problem: the…

  • How Do SQL Database Engines Work?

    How Do SQL Database Engines Work?

    To many programmers, SQL RDBMS is a magical black box. A document can help clear up a lot of the mystery.

  • Artificial Intelligence vs Machine Learning

    Artificial Intelligence vs Machine Learning

    For dummies - In memory of Margarita, my grandmother! What about Artificial Intelligence (I.A.

  • Python is powerful but could be tricky

    Python is powerful but could be tricky

    What keep in mind to avoid the tricky and get the power Python is an interpreted, high-level, general-purpose…

  • Do you want to take speed in the development software process? (II)

    Do you want to take speed in the development software process? (II)

    Without libraries what have we? We have no past and no future! In programming, a library is a collection of…

  • Do you want to take speed in the development software process?

    Do you want to take speed in the development software process?

    Yes please, a library! A static for now! As we develop software, we realize that some parts of the code are used in…

社区洞察

其他会员也浏览了