Linux и оперативная память

В этой статье будет рассмотрена общая информация о том, как в Linux используется оперативная память. Разберём основные моменты и термины.















Общая информация




Вся оперативная память в системе Linux делится на страницы. Страница — это минимальная единица памяти, с которой происходит работа. По размеру страницы разделяются на:




  • стандартная = 4KB;
  • HugePages = 2MB.




Помимо страниц память делится на зоны:




  • DMA — эта зона занимает 16MB;
  • DMA32 — эта зона занимает 4 GB и существует только на 64-разрядных системах;
  • Normal — вся остальная память.




Зоны DMA и DMA32 содержат страницы, которые совместимы с режимом DMA. Режим DMA (direct memory access) — это прямой доступ к памяти со стороны периферийного устройства без участия процессора. Если оборудование работает с памятью в режиме DMA, то оно занимает память из этой зоны и не может брать страницы из зоны Normal.




В оперативной памяти хранятся:




  • данные ядра;
  • данные процессов;
  • файлы, которые были прочитаны с жесткого диска или записаны на него.




За выделение оперативной памяти отвечает ядро Linux.




Виртуальная и резидентная память




Выделяемая память процессу может быть либо резидентная, либо виртуальная. В листинге ниже видно у процессов резидентную (rss) и виртуальную память (vsz). Эта память отображается в KB.




$ ps -C apache2 -o pid,user,rss,vsz,comm
    PID USER       RSS    VSZ COMMAND
    403 root      7316  11188 apache2
    405 www-data  7032 1216200 apache2
    406 www-data 11128 1216200 apache2




Виртуальная память (VSZ) — это память которую выделили процессу, но не факт что он успел в эту память что-то записать.




Резидентная память (RSS) — это память которую процесс занял, то есть что-то сохранил в виртуальную память. Именно резидентная память показывает сколько процесс потребляет физической памяти.




Приложение может запросить много памяти, а использовать малую её часть. Поэтому почти всегда rss меньше чем vsz.




Раздел или файл подкачки




Раздел подкачки (SWAP) — это раздел на жестком диске, куда помещаются:




  • редко используемые данные из резидентной памяти;
  • любые данные при нехватки физической памяти.




Если какие-то данные из rss сбрасываются в swap то rss освобождается, а vsz нет. От сюда следует что данные процесса, которые лежат в swap, входят в виртуальную память этого процесса.




Linux умеет работать не только с разделом подкачки, но и с файлом подкачки. То есть данные из резидентной памяти могут сбрасываться в специальный файл, который лежит на жёстком диске.




И файл и раздел подкачки имеет тот же самый формат что и оперативная память. То есть данные в оперативной памяти хранятся в виде страниц, и в подкачку сбрасываются в виде таких же страниц.




Память процессов




Посмотреть более подробно на используемую память процесса поможет файл /proc/<pid>/status. Из предыдущего листинга видно что процесс с номером pid=406 занимает 11128 KB памяти.




$ grep Rss /proc/406/status
RssAnon:            8328 kB
RssFile:            2736 kB
RssShmem:             64 kB




  • RssAnon — rss не сопоставляемая с каким-нибудь файлом на диске;
  • RssFile — rss сопоставляемая с каким-нибудь файлом на диске;
  • RssShmem — rss разделяемая память, которая может использоваться другими процессами (Shared Memory);




В этом же файле можно посмотреть на виртуальную память:




$ grep Vm /proc/406/status
VmPeak:  1281736 kB
VmSize:  1216200 kB
VmLck:         0 kB
VmPin:         0 kB
VmHWM:     11128 kB
VmRSS:     11128 kB
VmData:   225044 kB
VmStk:       132 kB
VmExe:       316 kB
VmLib:      5024 kB
VmPTE:       240 kB
VmSwap:        0 kB




  • VmPeak — пиковый размер использования виртуально памяти;
  • VmSize — размер виртуальной памяти в данный момент;
  • VmHWM — пиковый размер использования резидентной памяти;
  • VmRSS — размер резидентной памяти в данный момент;
  • VmExe — код приложения;
  • VmLib — используемые библиотеки;
  • VmSwap — часть данных сброшенная на раздел подкачки.




Когда память выделяется процессу то обычно выделяется не одна страница памяти, а какой-то блок. Такой блок страниц памяти называется virtual memory area (VMA). Такой группе сразу назначаются права:




  • r — можно читать данные из памяти;
  • w — можно записывать данные в памяти;
  • e — можно выполнять исполняемые файлы.




Также группе назначаются и друге параметры, например:




  • p — приватная память для данного процесса;
  • s — общая память (shared memory).




Страничный кеш




Больше всего в системе память занимает страничный кеш (Page Cache). Вся работа с файлами на диске (запись или чтение) идет через Page Cache. Запись в linux всегда быстрее чтения, так как запись вначале идет в Page Cache, а затем сбрасывается на диск. А при чтении ядро ищет файл в Page Cache, и если не находит читает файл с диска. Узнать сколько сейчас система тратит памяти на Page Cache можно выполнив команду free:




$ free -h
               total        used        free      shared  buff/cache   available
Mem:           976Mi        74Mi       764Mi       0,0Ki       137Mi       765Mi
Swap:          974Mi          0B       974Mi




Страничный кеш показан в колонке buff/cache. Как мы видим у нас занято 137MB страничным кешем. Хотя тут не только Page Cache, тут также находится Buffer, который тоже связан с файлами на диске.




Посмотреть информацию по Page Cache и Buffer отдельно можно в файле /proc/meminfo:




$ egrep "^Cach|^Buff" /proc/meminfo
Buffers:           16012 kB
Cached:           101220 kB




При создании нового файла, запись идет в cache, а страницы памяти для этого файла помечаются как грязные (dirty). Раз в какой-то промежуток времени грязные страницы сбрасываются на диск, и если таких страниц будет слишком много, то они тоже сбросятся на диск. Управлять этим можно через параметры sysctl ($ sudo nano /etc/sysctl.conf):




  • vm.dirty_expire_centisecs — интервал сброса грязных страниц на диск в сотых долях секунд (100 = 1с);
  • vm.dirty_ratio — объем оперативной памяти в процентах который может быть выделен под Page Cache.




$ sudo sysctl vm.dirty_expire_centisecs
vm.dirty_expire_centisecs = 3000

$ sudo sysctl vm.dirty_ratio
vm.dirty_ratio = 20




Существует утилита — vmtouch, она может показать какой процент указанного файла находится в страничном кеше. Но её нужно скачивать из git и устанавливать:




$ sudo apt update
$ sudo apt install git make gcc
$ git clone https://github.com/hoytech/vmtouch.git
$ cd vmtouch
$ make
$ sudo make install

$ vmtouch /etc/passwd
           Files: 1
     Directories: 0
  Resident Pages: 1/1  4K/4K  100%
         Elapsed: 6.3e-05 seconds




Видно что весь файл /etc/passwd сейчас находится в Page Cache (Resident Pages).




Узнать объем грязных страниц можно из файла /proc/meminfo. А команда sync записывает грязные страницы на диск:




$ grep Dirty /proc/meminfo
Dirty:                24 kB
# sync
$ grep Dirty /proc/meminfo
Dirty:                 0 kB




HugePages




Поговорим немного про большие страницы HugePages. Особенности таких страниц:




  • размер таких страниц равен 2MB;
  • приложение должно уметь работать с такими страницами;
  • эти страницы никогда не сбрасываются в swap.




Выделить под HugePages страницы можно параметром sysctl:




  • vm.nr_hugepages = <число страниц> (так если указать 1024 то выделится 1024*2МБ=2048MB).
  • vm.hugetlb_shm_group = <gid> — только члены этой группы могут использовать HugePages.




После исправления /etc/sysctl.conf нужно перезагрузиться и посмотреть на результат в файле /proc/meminfo:




$ egrep "HugePages_T|HugePages_F" /proc/meminfo
HugePages_Total:    1024
HugePages_Free:     1024




Выделено 1024 страниц и все они свободны. При этом у нас 2GB памяти не сможет использоваться обычными приложениями, которые не умеют работать с HugePages. Поэтому не всегда нужно выделять HugePages.









Итог




Вот мы и узнали как в Linux используется оперативная память. Оперативная память разбивается на страницы по 4KB, а при определенных настройках можно выделить большие страницы (2MB), которые называются HugePages. Ещё оперативная память в Linux разбивается на зоны: DMA, DMA32, Normal.




В оперативной памяти хранятся данные пользовательских процессов, данные ядра и файлы которые дублируются с диска.




Память которая выделяется процессам может быть виртуальная (vsz) или резидентная (rss). При этом память выделяется блоками страниц, которые называются virtual memory area (VMA). И этому блоку назначаются определенные атрибуты.




Есть раздел подкачки, куда сбрасывается резидентная память при необходимости.




Работа с файлами на диске также идет через оперативную память, для этого выделяется Cache и Buffer. Страницы которые изменились в памяти но не изменились на диске помечаются грязными (Dirty). Грязные страницы записываются на диск по расписанию или утилитой sync.




Файлы для исследование памяти:




  • /proc/<pid>/status
  • /proc/meminfo




Утилиты для исследования памяти:




  • ps
  • free
  • vmtouch




Настраивать работу с памятью можно через параметры sysctl (/etc/sysctl.conf):




  • vm.dirty_expire_centisecs — интервал сброса грязных страниц;
  • vm.dirty_ratio — объем оперативной памяти в процентах который может быть выделен под Page Cache;
  • vm.nr_hugepages — число больших страниц, которые нужно выделить;
  • vm.hugetlb_shm_group — группа, члены которой могут работать с большими страницами.










2022-10-28T14:50:48
Администрирование Linux