How to list processes attached to a shared memory segment in linux?
I don’t think you can do this with the standard tools. You can use ipcs -mp to get the process ID of the last process to attach/detach but I’m not aware of how to get all attached processes with ipcs .
With a two-process-attached segment, assuming they both stayed attached, you can possibly figure out from the creator PID cpid and last-attached PID lpid which are the two processes but that won’t scale to more than two processes so its usefulness is limited.
The cat /proc/sysvipc/shm method seems similarly limited but I believe there’s a way to do it with other parts of the /proc filesystem, as shown below:
When I do a grep on the procfs maps for all processes, I get entries containing lines for the cpid and lpid processes.
For example, I get the following shared memory segment from ipcs -m :
------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 123456 pax 600 1024 2 dest
and, from ipcs -mp , the cpid is 3956 and the lpid is 9999 for that given shared memory segment (123456).
Then, with the command grep 123456 /proc/*/maps , I see:
/proc/3956/maps: blah blah blah 123456 /SYSV000000 (deleted) /proc/9999/maps: blah blah blah 123456 /SYSV000000 (deleted)
So there is a way to get the processes that attached to it. I’m pretty certain that the dest status and (deleted) indicator are because the creator has marked the segment for destruction once the final detach occurs, not that it’s already been destroyed.
So, by scanning of the /proc/*/maps «files», you should be able to discover which PIDs are currently attached to a given segment.
How to know shared memory between two processes?
I need to know the amount of memory shared between two processes, that is, the intersection of their shared memories. Any ideas?
Which OS? Do you just want a number like «5342 kilobytes», or do you want to know which objects are shared?
@MarkPlotnick : I guess OP has explicitly mentioned «Amount of memory» So I don’t think he is looking for «which objects are shared.»
Are you interested in just shared memory segments ( shmget() ), or also shared memory due to process fork & copy-on-write, mmap() ped files, etc?
1 Answer 1
You can look at /proc//maps, /proc//smaps (or pmap -x if your OS supports) of interested process ID’s and compare outputs to determine shared memory regions. That includes shared memory segments via shmget calls, as well as any shared libraries, files.
Edit: As mr.spuratic pointed out his answer here has more details on kernel side
You can look at a process RSS using ps, however it doesn’t take into consideration all the shared pages. To see RSS for specific process, see below
cv@thunder:~$ ps -o rss,pid,comm -p $$,7023 RSS PID COMMAND 22060 7023 xfwm4 6876 18094 bash
smem tool provides more detailed information, taking into consideration of shared pages. See below output for the same above process
cv@thunder:~$ smem -t |egrep "RSS|$$|7023" PID User Command Swap USS PSS RSS 9852 cv grep -E RSS|18094|7023 0 340 367 2220 18094 cv bash 0 3472 4043 6876 7023 cv xfwm4 --display :0.0 --sm-c 0 5176 7027 22192
smem reports physical memory usage, taking shared memory pages into account. Unshared memory is reported as the USS (Unique Set Size). Shared memory is divided evenly among the processes sharing that memory. The unshared memory (USS) plus a process's proportion of shared memory is reported as the PSS (Proportional Set Size). The USS and PSS only include physical memory usage. They do not include memory that has been swapped out to disk.
Sysadminium
В этой статье будет рассмотрена общая информация о том, как в Linux используется оперативная память. Разберём основные моменты и термины.
Общая информация
Вся оперативная память в системе Linux делится на страницы. Страница — это минимальная единица памяти, с которой происходит работа. По размеру страницы разделяются на:
Помимо страниц память делится на зоны:
- 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//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 = — только члены этой группы могут использовать 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.
Файлы для исследование памяти:
Утилиты для исследования памяти:
Настраивать работу с памятью можно через параметры sysctl (/etc/sysctl.conf):
- vm.dirty_expire_centisecs — интервал сброса грязных страниц;
- vm.dirty_ratio — объем оперативной памяти в процентах который может быть выделен под Page Cache;
- vm.nr_hugepages — число больших страниц, которые нужно выделить;
- vm.hugetlb_shm_group — группа, члены которой могут работать с большими страницами.