Главное меню » Практика » Как узнать размер физической памяти системы

Как узнать размер физической памяти системы

Функции API, позволяющие получить размер физической памяти (RAM) существенно различаются между Windows, Linux, OSX, AIX, BSD, Solaris и другими операционными системами. В данной статье мы попытались написать кросс-платформенную функцию, позволяющую получить размер физический памяти системы.

Как получить размер физической памяти

Физическая память — это тот объём памяти, которым системе располагает на самом деле (в отличие от памяти виртуальной). Размер свободной физической памяти задаёт тот верхний предел при выделении доплнительной памяти процессом, достигая которого, он будет выгружен на диск. На практике некоторая часть физической памяти постоянно выделена под ядро и другие сервисы, которые должны остаться в памяти резидентно. Остальная часть физической памяти находится под управлением операционной системы и распределяется между всеми запущенными процессами. Ни один один пользовательский процесс никогда не сможет получить всю физическую память.
Каждая ОС имеет консольные или GUI-инструменты для получения информации о размере физической памяти, но перед нами стоит задача получения этой информации программным путем. К сожалению, функции API, позволяющие получить размер физической памяти не стандартизированы и сильно отличаются в различных ОС.

Код

Собственно речь пойдет о функции getMemorySize(). Представленная работает для большинства операционных систем (вы можете просто скопировать код, или скачать getMemorySize.c). Подключать какие-либо дополнительные библиотеки не требуется.

Для использования функции достаточнло ее вызвать следующим образом:

Функция возвращает размер физической памяти в байтах. В случае ошибки, функция возвращает 0.

Подробности

Каждая ОС имеет свой специфический способ получения размер физической памяти:

Операционная система Метод получения информации
AIX sysconf() с параметром _SC_AIX_REALMEM
Cygwin GlobalMemoryStatus()
DragonFly BSD sysctl() с параметром HW_PHYSMEM
FreeBSD sysconf() с парметром _SC_PHYS_PAGES, или sysctl() параметром HW_REALMEM или HW_PHYSMEM
Linux sysconf() с параметром _SC_PHYS_PAGES, sysinfo(), или /proc/meminfo
NetBSD sysctl() с параметром HW_PHYSMEM64 или HW_PHYSMEM
OpenBSD sysconf() с параметром _SC_PHYS_PAGES, или sysctl () с параметром HW_PHYSMEM64 или HW_PHYSMEM
OSX sysconf() с параметром _SC_PHYS_PAGES, или sysctl( ) с параметром HW_MEMSIZE или HW_PHYSMEM
Solaris sysconf( ) с параметром _SC_PHYS_PAGES
Windows GlobalMemoryStatus() или GlobalMemoryStatusEx()

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

GlobalMemoryStatus() и GlobalMemoryStatusEx()

В операционной системе Windows и Cygwin(UNIX-подобная среда и интерфейс командной строки для Microsoft Windows), используется функция GlobalMemoryStatus(), которая заполняет структуру MEMORYSTATUS информацией о системной памяти. Описание этой структуры представленно ниже:

Поле dwTotalPhys содержит размер физической памяти в байтах. Однако, размер этого поля позволяет хранить только 32-разрядные целые числа. Для систем с более чем 4-мя гигабайтами памяти, поле устанавливается равным -1.
В операционной системе Windows (но НЕ в Cygwin), доступна новая функция GlobalMemoryStatusEx(), которая заполняет структуру MEMORYSTATUSEX информацией о физической и виртуальной памяти. Эта структура включают в себя следующие поля:

В этой структур 64-битное поле ullTotalPhys содержит размер физической памяти в байтах.
Обратите внимание: Функция GetPhysicallyInstalledSystemMemory() (поддерживается Vista, и Windows более поздних версий) возвращает размер всей памяти, установленной в системе. Это значение определяется BIOS и может быть больше, чем значение, сообщаемое функцией GlobalMemoryStatusEx(), если BIOS и низкоуровневые драйверы резервируют некоторый объем памяти. Не смотря на то, что значение получаемое при помощи GetPhysicallyInstalledSystemMemory() может быть более близким к реальности, это будет для нас менее полезно. Наша цель — получение информации об объеме памяти, который на самом деле доступен для использования операционной системой и запущенными процессами.
Поддерживается: Cygwin и Windows начиная с Windows XP.
Вот как мы используем описанные функции в нашем коде:

sysconf()

В AIX, FreeBSD, Linux, OpenBSD и Solaris, sysconf() возвращает основную информацию о конфигурации системы (см. man’ы для AIX, FreeBSD, Linux, OpenBSD, OSX и Solaris). Для FreeBSD и OpenBSD, функция доступна, но sysctl() предоставляет более полную информацию и позволяет более точно измерить доступный объем физической памяти (см. ниже).
Функция sysconf() принимает в качестве аргумент идентификатор атрибута и возвращает длинное целое в качестве значения указанного атрибута. Хотя sysconf() и определяется в POSIX, идентифиактор атрибута для определение размера физической памяти не стандартизирован и варьируется в зависимости от ОС:

ОС Имя атрибута Точность
AIX _SC_AIX_REALMEM Размер физической памяти в килобайтах
FreeBSD, Linux, OpenBSD, Solaris _SC_PHYS_PAGES Размер физической памяти в страницах

Чтобы преобразовать размер памяти в страницах в байты, умножьте его на размер страницы, котрый можно получить при помощи sysconf(), используя атрибут _SC_PAGESIZE (или _SC_PAGE_SIZE). FreeBSD, Linux и OpenBSD также поддерживают функцию getPageSize(), которая возвращает то же значение. При вычислении размера физической памяти размер страницы округляется до ближайшей границы страницы, и может быть немного меньше, чем фактический размер памяти в системе.
Поддерживается: AIX, FreeBSD, Linux, OpenBSD и Solaris.
Пример использования:

sysctl()

Для BSD и OSX, sysctl() является предпочтительным способом, для получения широкого спектра информации о конфигурации системы (см. man’ы для DragonFly BSD, FreeBSD, NetBSD, OpenBSD, и OSX). Linux также поддерживает эту функцию, но она устарела и настоятельно рекомендуется использовать вместо нее sysconf() (см. выше).
Функция sysctl() принимает массив целых чисел, которые указывают идентификаторы атрибутов, информация по которым будет запрошена. В случае успеха, функция заполняет указанную переменную значением атрибута. Атрибуты сгруппированы в иерархическом порядке и включают в себя информацию об аппаратных средствах, ядре, сети, виртуальной памяти, и многое другое. Атрибуты информации об аппаратных средствах группируются по CTL_HW. Атрибут для получения размера физической памяти варьируется в зависимости от операционной системы:

ОС Имя атрибута Значение
FreeBSD HW_REALMEM Размер физический памяти в байтах (32-битное целое число)
DragonFly BSD, FreeBSD, NetBSD, OpenBSD, OSX HW_PHYSMEM Размер физический памяти в байтах (32-битное целое число)
NetBSD, OpenBSD HW_PHYSMEM64 Размер физический памяти в байтах (64-битное целое число)
OSX HW_MEMSIZE Размер физический памяти в байтах (64-битное целое число)

«Старый» атрибут HW_PHYSMEM доступен для BSD и OSX, но он возвращает 32-разрядное целое число, которого не достаточно, если размер памяти более 2 Гбайт. Для получения объема памяти в виде 64-битного числа, используйте HW_PHYSMEM64 на NetBSD и OpenBSD, и HW_MEMSIZE на OSX. К сожалению, FreeBSD и DragonFly BSD в настоящее время не поддерживают этот атрибут, что не позволяет получить объем памяти в виде 64-битного числа.
FreeBSD и OpenBSD обеспечивают поддержку как sysctl() так и sysconf() (смотри выше), для получения размера физической памяти. Использование sysctl() позволяет получить более точные данные, так как sysctl() возвращает размер в байтах, в то время как sysconf() при расчёте размера памяти производит округление вниз до ближайшей границы страницы.
FreeBSD обеспечивает как HW_REALMEM и HW_PHYSMEM. Оба эти атрибута возвращают 32-разрядные числа, но значение HW_PHYSMEM округляется до ближайшей границы страницы (как и при вызове sysconf()), в то время как значение, вычисленное для HW_REALMEM, такому округлению не подверженно. При выборе между HW_PHYSMEM и sysconf(), следует отдать предпочтение sysconf(). Хотя sysconf() возвращает 32-разрядное число, это значение выраженно это в количестве страниц, размер страницы обычно составляет 4 Кбайт. Это добавляет еще 12 бит, что возволяет увеличть максимальный размер памяти, который может быть пердставлен, до 16 Тбайт.
Поддерживается: DragonFly BSD, FreeBSD, NetBSD, OpenBSD, and OSX.
Пример использования:

sysinfo()

В Linux, функция sysinfo() заполняет sysinfo-структуру, содержащую информацию о системе. Структура имеет следующие поля:

До Linux 2.3.23 в структуре sysinfo были опущены последние четыре поля и все размеры были в байтах. На сегодняшний день, все поля структуры используются и все размеры выраженны в единицах, заданных полем mem_unit. Значение поля totalram умноженное на значние поля mem_unit дает размер физической памяти в байтах.
Поскольку использование sysinfo для наших целей является излишним, функция getMemorySize(), описываемая в этой статье, использует sysconf() вместо sysinfo().
Поддерживается: Linux.
Пример использования:

/proc/meminfo

В Linux, псевдо-файловая система /proc включает в себя несколько псевдо-файлов, содержащих информацию о конфигурации системы. Псевдо-файл /proc/memInfo содержит подробную информацию об использовании памяти. Вот пример его содержимого для 64-битной Ubuntu Linux 12:

MemTotal: 3016120 kB
MemFree: 2188204 kB
Buffers: 25852 kB
Cached: 322260 kB
SwapCached: 0 kB
Active: 420580 kB
Inactive: 293120 kB
Active(anon): 366248 kB
Inactive(anon): 16356 kB
Active(file): 54332 kB
Inactive(file): 276764 kB
Unevictable: 12 kB
Mlocked: 12 kB
SwapTotal: 1046524 kB
SwapFree: 1046524 kB
Dirty: 16 kB
Writeback: 0 kB
AnonPages: 365632 kB
Mapped: 94504 kB
Shmem: 17016 kB
Slab: 37596 kB
SReclaimable: 19352 kB
SUnreclaim: 18244 kB
KernelStack: 2552 kB
PageTables: 22428 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 2554584 kB
Committed_AS: 2037044 kB
VmallocTotal: 34359738367 kB
VmallocUsed: 21548 kB
VmallocChunk: 34359713720 kB
HardwareCorrupted: 0 kB
AnonHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB
DirectMap4k: 38848 kB
DirectMap2M: 3106816 kB

Формат файла немного меняется от одного дистрибутива Linux к другому, но все они имеют строку MemTotal, предоставляющую размер физической памяти в килобайтах. Это значение может быть немного меньше фактического размера физической памяти, поскольку оно исключает память, используемую ядром.
Парсинг псевдо-файла /proc/memInfo медленнее и требует больших ресурсов, чем вызов sysinfo() или sysconf() (см. выше). Поэтому, описываемая в этой статье функция getMemorySize(), использует более простой способ с вызовом sysconf().
Поддерживается: Linux.
Пример использования:

Другие методы получения информации о размере физической памяти

Каждая ОС с оконным интерфейсом имеет некое подобие панели управления, которая позволяет посмотреть размер установленной памяти. В операционной системе Windows есть апплет панели управления — «Система». На OSX, можно выбрать пункт «Об этом компьютере» из меню Apple. В Solaris, есть пункт меню «Об Oracle Solaris» в меню «System». Для Ubuntu Linux, выберите «Details» в панели управления. И так далее.
У каждая ОС, которая поддерживает интерфейс командной строки, присутствуют команды, которые выводят информацию о конфигурации системы. В операционной системе Windows см. команду systeminfo. В Linux, см. free и vmstat. На BSD и OSX, используйте sysctl. На OSX, можно использовать system_profiler. В Solaris, есть prtconf.

Что еще почитать?

Источник: http://nadeausoftware.com