Курсовая работа: Мониторинг виртуальной памяти в ОС Linux
execve (»./test3», [«test3»], [/* 61 vars */]) = 0
…
fsync(0) = -1 EINVAL (Invalid argument)
mmap2 (NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7bf4000
fsync(1) = -1 EINVAL (Invalid argument)
fsync(2) = -1 EINVAL (Invalid argument)
munmap (0xb7bf4000, 2101248) = 0
exit_group(0)
На приведенной трассировке видно, как процесс выделяет и освобождает 2101248 байт памяти. К сожалению, это средство не позволяет следить за всеми процессами в системе в целом, а так же за выделениями физических страниц процессу.
Таким образом, возникает необходимость в средстве, позволяющем отслеживать не только выделения виртуальной памяти процессу, но и выделения отдельных страниц физической памяти в результате страничных сбоев.
1. Аналитический раздел
1.1 Постановка задачи
Разработать драйвер под Linux, отслеживающий выделение и освобождение процессами виртуальной памяти и выделение физических страниц при страничных отказах.
Драйвер должен поддерживать динамическую загрузку и выгрузку без перезапуска системы и задание списка процессов, за которыми необходимо выполнять мониторинг.
Взаимодействие с пользовательской программой осуществляется посредством файлов, создаваемых в файловой системе /proc .
Ядро отвечает за создание и уничтожение процессов и за их связь с внешним миром (ввод и вывод). Взаимодействие процессов друг с другом (посредством сигналов, программных каналов или других средств межпроцессного взаимодействия) является основой общей системной функциональности, и тоже осуществляется при помощи ядра. Планировщик, распределяющий время центрального процессора между процессами, является частью подсистемы управления процессами. В общих словах, подсистема управления процессами реализует абстракцию множества процессов, работающих одновременно на одном или нескольких процессорах.
1.1.1 Управление памятью
Память компьютера – один из главных ресурсов, и производительность системы критически зависит от политики распределения памяти. Ядро создает виртуальное адресное пространство для каждого процесса, используя при этом ограниченное количество физической памяти и, при необходимости, вторичную память, такую, как жесткий диск. По мере необходимости страницы могут быть выгружены в файл подкачки, либо файл, из которого они были отображены в память (в случае, если они не были модифицированы с момента загрузки из файла, они просто удаляются из памяти). По умолчанию ядро не позволяет выделить одному процессу больше памяти, чем суммарный объем доступной оперативной и swap‑памяти. Однако есть такая возможность, как overcommit («перевыделение»), которая позволяет выделить гораздо больше памяти, при условии, что реально использоватьcя будет лишь небольшая ее часть (допустим, при работе с разреженным массивом). Overcommit включается командой
# echo 1 > /proc/sys/vm/overcommit_memory
а отключается
# echo 0 > /proc/sys/vm/overcommit_memory
Цифра 1 означает выбранный режим управления перевыделением (0 означает его отсутствие, 1 – допустимо перевыделение неограниченных объемов памяти, 2 – некоторый эвристический алгоритм определения максимально допустимого объема перевыделения).
1.1.2 Файловая система
Система Linux основана на концепции файловой системы. Практически любой объект системы может быть рассмотрен как файл. Ядро строит единую иерархическую файловую систему (единое дерево директорий) на основе не обладающего иерархической структурой оборудования. В результате абстракция файла активно используется всей системой.
1.1.3 Подсистема ввода-вывода
Практически любая операция в системе есть, по сути, операция с устройством. За исключением процессора, памяти и очень небольшого числа других элементов, порядок выполнения работы с устройством, а следовательно и исполняемый код, выполняющий эту работу, зависит главным образом от конкретного устройства. Такой код называется драйвером устройства. Ядро должно включать в себя драйверы для всех периферийных устройств, входящих в систему, от жесткого диска до клавиатуры.
1.1.4 Сетевая подсистема
Ядро должно управлять работой с сетью, поскольку большинство сетевых операций не зависит от процесса. Приходящие сетевые пакеты являются асинхронными событиями, т.е. во время работы одного процесса может прийти пакет, адресованный другому процессу. Пакеты должны быть приняты, распознаны и распределены до того, как о них узнает процесс. Система отвечает за передачу данных через программные и сетевые интерфейсы, а так же управлять выполнением программ в соответствии с работой сети. К тому же, все задачи маршрутизации и выделения сетевых адресов выполняет ядро.
1.1.5 Системные вызовы
Системные вызовы, такие как open() , fork() , read() , etc являются связующим интерфейсом между ядром и пользовательскими приложениями. В Linux 2.6 существует около 330 различных вызовов (многие из них избыточны или сохранены по причинами совместимости). Их вызов происходит через прерывание 0x80 или инструкцию sysenter (на современных процессорах). При этом в регистр EAX помещается номер системного вызова, а в остальные 6 регистров (кроме ESP ) – аргументы (т.е. любой системный вызов может принимать до шести 32‑битных аргументов) в порядке EBX, ECX, EDX, ESI, EDI, EBP . Точка входа всех системных вызовов расположена в файле arch/i386/kernel/entry.S , который вызывает обработчик конкретного вызова по таблице вызовов sys_call_table, передавая ей регистры через стек.
1.1.6 Загружаемые модули