• Linux uses a virtual memory system (VM), as do all modern operating systems: the virtual memory is larger than the physical memory.


  • Each process has its own, protected address space. Addresses are virtual and must be translated to and from physical addresses by the kernel whenever a process needs to access memory.


  • The kernel itself also uses virtual addresses; however the translation can be as simple as an offset depending on the architecture and the type of memory being used.


  • The kernel allows fair shares of memory to be allocated to every running process, and coordinates when memory is shared among processes. In addition, mapping can be used to link a file directly to a process’s virtual address space. Furthermore, certain areas of memory can be be protected against writing and/or code execution.


  • The free utility gives a very terse report on free and used memory in your system:


  •  
       $ free -mt
              total     used     free    shared    buff/cache   available 
    Mem:      15893     3363      175       788        12354        11399  
    Swap:      8095        0     8095
    Total:    23989     3363     8271 
        
     
    
  • where the options cause the output to be expressed in MB’s.


  • This system has 16 GB of RAM and a 8 GB swap partition. At the moment, this snapshot was taken the system was pretty inactive and not doing all that much. Yet, the amount of memory being used is appreciable (if you include the memory assigned to the cache).


  • However, a lot of the memory being used is in the page cache, most of which is being used to cache the contents of files that have recently been accessed. If this cache is released, the memory usage will decrease significantly. This can be done by doing (as root user):


  •  
        $ sudo su
    # echo 3 > /proc/sys/vm/drop_caches
    # exit
    $ free -mt
              total      used      free     shared     buff/cache    available
    Mem:      15893      3370     11103        788           1419        11419
    Swap:      8095         0      8095
    Total:    23989      3370     19199
        
        
     
    
  • If we had only wanted to drop the page cache, we would have echoed a 1, not a 3; we have also dropped the dentry and inode caches, which is why the freed memory is more than that released from the page cache.


  • A more detailed look can be obtained by looking at /proc/meminfo:


  •  
        
    $ cat /proc/meminfo
    
    MemTotal:       16275064 kB
    MemFree:        11059060 kB
    MemAvailable:   11525932 kB
    Buffers:           30416 kB
    Cached:          1598188 kB
    SwapCached:            0 kB
    Active:          3880768 kB
    Inactive:        1105144 kB
    Active(anon):    3295948 kB
    Inactive(anon):   994524 kB
    Active(file):     584820 kB
    Inactive(file):   110620 kB
    Unevictable:        3596 kB
    Mlocked:            3596 kB
    SwapTotal:       8290300 kB
    SwapFree:        8290300 kB
    Dirty:               416 kB
    Writeback:             0 kB
    AnonPages:       3360760 kB
    Mapped:           859028 kB
    Shmem:           1007708 kB
    Slab:              94048 kB
    SReclaimable:      46268 kB
    SUnreclaim:        47780 kB
    KernelStack:       14272 kB
    PageTables:        63688 kB
    NFS_Unstable:          0 kB
    Bounce:                0 kB
    WritebackTmp:          0 kB
    CommitLimit:    16427832 kB
    Committed_AS:   11194528 kB
    VmallocTotal:   34359738367 kB
    VmallocUsed:           0 kB
    VmallocChunk:          0 kB
    AnonHugePages:    980992 kB
    ShmemHugePages:        0 kB
    ShmemPmdMapped:        0 kB
    CmaTotal:              0 kB
    CmaFree:               0 kB
    HugePages_Total:       0
    HugePages_Free:        0
    HugePages_Rsvd:        0
    HugePages_Surp:        0
    Hugepagesize:       2048 kB
    DirectMap4k:      175384 kB
    DirectMap2M:     8087552 kB
    DirectMap1G:     9437184 kB
    
    
  • The output will depend somewhat on kernel version, and you should not write scripts that overly depend on certain fields being in this file.


  • In the following diagram (for 32-bit platforms), the first 3 GB of virtual addresses are used for user-space memory and the upper GB is used for kernel-space memory. Other architectures have the same setup, but differing values for PAGE_OFFSET; for 64-bit platforms, the value is in the stratosphere.


  • page_offset
  • While Linux permits up to 64 GB of memory to be used on 32-bit systems, the limit per process is a little less than 3 GB. This is because there is only 4 GB of address space (i.e. it is 32-bit limited) and the topmost GB is reserved for kernel addresses. The little is somewhat less than 3 GB because of some address space being reserved for memory-mapped devices.


  • It is important to remember that applications do not write directly to storage media such as disks; they interface with the virtual memory system and data blocks written are generally first placed into cache or buffers, and then are flushed to disk when it is either convenient or necessary. Thus, in most systems, more memory is used in this buffering/caching layer than for direct use by applications for other purposes.


  • Managing the memory on 32-bit machines with large amounts of memory (especially over 4 GB) is far more complex than it is in 64-bit systems.


  • It is hard to think of a good reason to be acquiring purely 32-bit hardware anymore for use as heavy iron; there is still plenty of use for 32-bit systems in the embedded world, etc., but there memory is not expected to be large enough to complicate memory management.


  • Linux employs a virtual memory system in which the operating system can function as if it had more memory than it really does. This kind of memory overcommission functions in two ways:


  • Many programs do not actually use all the memory they are given permission to use.


  • Sometimes, this is because child processes inherit a copy of the parent’s memory regions utilizing a COW (Copy On Write) technique, in which the child only obtains a unique copy (on a page-by-page basis) when there is a change.


  • When memory pressure becomes important, less active memory regions may be swapped out to disk, to be recalled only when needed again.


  • Such swapping is usually done to one or more dedicated partitions or files; Linux permits multiple swap areas, so the needs can be adjusted dynamically. Each area has a priority and lower priority areas are not used until higher priority areas are filled.


  • In most situations, the recommended swap size is the total RAM on the system. You can see what your system is currently using for swap areas with:


  •  
    $ cat /proc/swaps
    Filename            Type          Size        Used       Priority
    /dev/sda9           partition     4193776     0          -1
    /dev/sdb6           partition     4642052     0          -2 
    
    
  • and current usage with:


  •  
    $ free
              total       used       free     shared      buffers       cached
    Mem:    4047236    3195080     852156          0       818480      1430940
    Swap:   8835828          0    8835828
    
    
  • The only commands involving swap are mkswap for formatting a swap file or partition, swapon for enabling one (or all) swap area, and swapoff for disabling one (or all) swap area.


  • At any given time, most memory is in use for caching file contents to prevent actually going to the disk any more than necessary, or in a sub-optimal order or timing. Such pages of memory are never swapped out as the backing store is the files themselves, so writing out to swap would be pointless; instead, dirty pages (memory containing updated file contents that no longer reflect the stored data) are flushed out to disk.


  • It is also worth pointing out that Linux memory used by the kernel itself, as opposed to application memory, is never swapped out, in distinction to some other operating systems.


  • A process is simply a running instance of a program. So, it's something executing on your machine.


  • There's additional information besides the actual executing program, such as environmental variables, attached memory regions, what the current directory and files that are being used are, etc.


  • If you have multiple threads in a process, they share this information. For instance, they all share the same memory.


  • Well, there's a couple of reasons why it's good to have a multi-threaded program. For instance, you may be doing the same kind of task many times at once.


  • For instance, you could have a server, which is handling many clients, and for each client you will create a thread to handle that client, or you could have a process which is doing multiple things.


  • One thread may be waiting for the user to give it some input in the form of a mouse click or typing, while another thread is doing some actual work, etc.


  • There are number of ways to code multi-threaded programs, but the portable way is to use a so-called POSIX threads library or pthreads library.


  • The idea here is you can write it once, and use it anywhere on any system which has a pthreads implementation, which you will generally find on all Unix-based operating systems for instance, like Solaris, or AIX, or HPUX etc.


  • However, the ideal of write once, and use anywhere, and complete portability, is just an ideal.


  • There are cases where a program written on Linux won't work on Solaris properly and vice versa. This often happens for instance when there's some behavior which isn't very well defined in the library itself, and people make different assumptions.


  • For instance, Solaris will tend to automatically initialize improperly uninitialized mutexes. Linux will not and you may get program crashes.


  • So, you always have to test on other operating systems. But if you start with pthreads, you're starting in a much stronger place. So, that's just a little bit of explanation of the concept of threads and processes.