Мониторинг виртуальной памяти в ОС Linux

Разработка драйвера под Linux, отслеживающего выделение и освобождение процессами виртуальной памяти и выделение физических страниц при страничных отказах. Компиляция драйвера и работа с ним. Экспериментальная проверка работоспособности драйвера.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 18.06.2009
Размер файла 43,5 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

#endif //MEMMON_SYSCALLS_H

syscalls.c

/*

* Syscall capture facility.

*/

#include <linux/module.h>

#include <linux/moduleparam.h>

#include <linux/kernel.h>

#include <linux/proc_fs.h>

#include «common.h»

#include «syscalls.h»

#include «events.h»

#include «watch-pids.h»

/*** Syscalls ***/

/*

* They just put an appropriate event into ringbuffer

*/

asmlinkage void sys2_mmap2 (void __user *start, size_t length,

unsigned long prot, unsigned long flags,

unsigned long fd, unsigned long pgoff)

{

struct memmon_event ev = {.type = MMAP2.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.mmap2.start = start;

ev.mmap2.len = length;

ev.mmap2.prot = prot >> 3;

ev.mmap2.flags = flags;

ev.mmap2.fd = fd;

ev.mmap2.off = pgoff;

put_event(&ev);

}

asmlinkage void sys2_mmap2_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «mmap»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_munmap (void __user *start, size_t length)

{

struct memmon_event ev = {.type = MUNMAP.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.munmap.start = start;

ev.munmap.len = length;

put_event(&ev);

}

asmlinkage void sys2_munmap_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «munmap»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_mremap (void __user *addr1, size_t length1,

unsigned long length2, unsigned long flags,

void __user *addr2)

{

struct memmon_event ev = {.type = MREMAP.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.mremap.start[0] = addr1;

ev.mremap.start[1] = addr2;

ev.mremap.len[0] = length1;

ev.mremap.len[1] = length2;

ev.mremap.flags = flags;

put_event(&ev);

}

asmlinkage void sys2_mremap_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «mremap»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_mlock (void __user *start, size_t length)

{

struct memmon_event ev = {.type = MLOCK.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.mlock.start = start;

ev.mlock.len = length;

put_event(&ev);

}

asmlinkage void sys2_mlock_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «mlock»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_munlock (void __user *start, size_t length)

{

struct memmon_event ev = {.type = MUNLOCK.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.munlock.start = start;

ev.munlock.len = length;

put_event(&ev);

}

asmlinkage void sys2_munlock_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «munlock»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_mlockall (unsigned long flags)

{

struct memmon_event ev = {.type = MLOCKALL.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.mlockall.flags = flags;

put_event(&ev);

}

asmlinkage void sys2_mlockall_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «mlockall»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_munlockall()

{

struct memmon_event ev = {.type = MUNLOCKALL.pid = current->pid};

if (! pid_present (ev.pid)) return;

put_event(&ev);

}

asmlinkage void sys2_munlockall_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «munlockall»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_brk (void __user *start)

{

struct memmon_event ev = {.type = BRK.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.brk.addr = start;

put_event(&ev);

}

asmlinkage void sys2_brk_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «brk»;

ev.callret.ret = ret;

put_event(&ev);

}

asmlinkage void sys2_fsync (int fd)

{

struct memmon_event ev = {.type = FSYNC.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.fsync.fd = fd;

put_event(&ev);

}

asmlinkage void sys2_fsync_exit (long ret)

{

struct memmon_event ev = {.type = SYSCALLRET.pid = current->pid};

if (! pid_present (ev.pid)) return;

ev.callret.callname = «fsync»;

ev.callret.ret = ret;

put_event(&ev);

}

/*** Handler tables ***/

/* Kernel syscall table */

extern void *sys_call_table[];

/* Our table w/saved offsets */

void *old_sys_call [NR_syscalls];

/* Our pre-call handlers */

void *sys_call_trap [NR_syscalls];

/* Our post-call handlers */

void *sys_call_exit [NR_syscalls];

/*

* Struct describind our handler

*/

struct syscall_handler

{

/* Syscall nr */

int nr;

/* Pre-call & post-call handler */

void *hand1, *hand2;

};

#define SYSCALL_HANDLER(name) {__NR_##name, sys2_##name, sys2_##name##_exit}

#define SYSCALL_HANDLERS_END() {0, 0, 0}

/*

* Main handler table

* Each SYSCALL_HANDLER(name) entry installs handlers

* «sys2_name/sys2_name_exit for sys_name call.

*/

struct syscall_handler syscalls[] =

{

SYSCALL_HANDLER(mmap2),

SYSCALL_HANDLER(munmap),

SYSCALL_HANDLER(mremap),

SYSCALL_HANDLER(mlock),

SYSCALL_HANDLER(munlock),

SYSCALL_HANDLER(mlockall),

SYSCALL_HANDLER(munlockall),

SYSCALL_HANDLER(brk),

SYSCALL_HANDLER(fsync),

SYSCALL_HANDLERS_END()

};

/* Located in syscall-entry.S */

void syscalls_entry(void);

/*** Exported entries ***/

/*

* Installs handlers.

*/

int capture_syscalls(void)

{

int i;

for (i = 0; syscalls[i].hand1; ++i)

{

int nr = syscalls[i].nr;

sys_call_trap[nr] = syscalls[i].hand1;

sys_call_exit[nr] = syscalls[i].hand2;

old_sys_call[nr] = sys_call_table[nr];

sys_call_table[nr] = syscalls_entry;

}

return 1;

}

/*

* Uninstalls handlers

*/

void restore_syscalls(void)

{

int i;

for (i = 0; syscalls[i].hand1; ++i)

{

int nr = syscalls[i].nr;

sys_call_table[nr] = old_sys_call[nr];

}

}

syscalls-entry.S

/*

* Syscall entry/exit capture

*/

#include «offsets.h»

/* Entry handler table */

extern sys_call_trap

/* Exit handler table */

extern sys_call_exit

/* Global entry for our syscalls */

syscalls_entry:

/* Save registers in order syscall handlers expect 'em */

pushl %eax

pushl %ebp

pushl %edi

pushl %esi

pushl %edx

pushl %ecx

pushl %ebx

/* Save eax */

movl %eax, TI_stk0 (%ebp)

/* Call our handler */

call *sys_call_trap (,%eax, 4)

/* Fake return address */

movl 28 (%esp),%eax

movl %eax, TI_stk0 + 4 (%ebp)

movl $sysreturn, 28 (%esp)

/* Restore context */

popl %ebx

popl %ecx

popl %edx

popl %esi

popl %edi

popl %ebp

popl %eax

/* Jump to default system handler */

jmpl *old_sys_call (,%eax, 4)

sysreturn:

/* Save registers */

pushal

/* Pass new% eax to exit handler */

pushl %eax

/* Restore original% eax */

movl TI_stk0 (%ebp),%eax

/* Call our exit handler */

call *sys_call_exit (,%eax, 4)

/* Restore context */

popl %eax

popal

/* Jump back to syscall dispatcher entry */

jmpl *TI_stk0 + 4 (%ebp)

globl syscalls_entry

gen-offsets.c

//

#define __KERNEL__

/* bugoga */

#include <linux/kernel.h>

#include <linux/autoconf.h>

#include <linux/thread_info.h>

#include <stdio.h>

int main()

{

printf («#define TI_stk0% d\n», offsetof (struct thread_info, supervisor_stack));

return 0;

}

mm-fault.h

/*

* Pagefault interception.

*/

#ifndef MEMMON_MM_FAULT_H

#define MEMMON_MM_FAULT_H

/*

* Install pagefault handler

*/

void capture_mmfault(void);

/*

* Uninstall handler

*/

void release_mmfault(void);

#endif // MEMMON_MM_FAULT_H

mm-fault.c

/*

* Pagefault interception.

*/

#include <linux/module.h>

#include <linux/moduleparam.h>

#include <linux/kernel.h>

#include <linux/mm.h>

#include «common.h»

#include «mm-fault.h»

#include «events.h»

#include «watch-pids.h»

/*

* Dirty kernel hack: PF hook that is called every time

* some process PF's for some page that BELONGS to his VMA space.

*/

extern void (*mm_handle_fault_hook) (struct mm_struct *mm, struct vm_area_struct *vma,

void __user *address, pte_t *pte,

pmd_t *pmd, int write_access);

/*

* Pagefault handler

*/

void mm_handle_fault (struct mm_struct *mm, struct vm_area_struct *vma,

void __user *address, pte_t *pte,

pmd_t *pmd, int write_access)

{

struct memmon_event ev = {.pid = current->pid};

pte_t entry = *pte;

/*

* If PF happened due to R/W or U/S access violation, ignore it

*/

if (! pid_present (current->pid) || pte_present(entry))

return;

/*

* Faulted page is either backed by swapfile, some shared executable file

* or no file yet at all (anonymous page)

*/

if (pte_none(entry))

ev.type = ANON_PF;

else if (pte_file(entry))

ev.type = FILE_PF;

else

ev.type = SWAP_PF;

ev.pagefault.addr = address;

ev.pagefault.write = write_access;

put_event(&ev);

}

/*** Exported entries ***/

/*

* Install pagefault handler

*/

void capture_mmfault(void)

{

mm_handle_fault_hook = mm_handle_fault;

}

/*

* Uninstall handler

*/

void release_mmfault(void)

{

mm_handle_fault_hook = NULL;

}

common.h

/*

* Common defines and global data

*/

#ifndef MEMMON_COMMON_H

#define MEMMON_COMMON_H

/* procfs directory name */

#define PROCDIR «memmon»

/*

* procfs directory entry

*/

extern struct proc_dir_entry *procdir;

#endif // MEMMON_COMMON_H

Makefile

#

ifneq ($(KERNELRELEASE),)

obj-m:= memmon.o

memmon-objs:= mmon.o events.o watch-pids.o syscalls.o syscalls-entry.o mm-fault.o

else

KERNELDIR?= /lib/modules/$(shell uname - r)/build

PWD:= $(shell pwd)

all: offsets.h modules

offsets.h: $(KERNELDIR)/include/asm/thread_info.h

$(MAKE) gen-offsets

gen-offsets > offsets.h

$(RM) gen-offsets

clean modules:

$(MAKE) - C $(KERNELDIR) M=$(PWD) $(MAKECMDGOALS)

PHONY: modules.DEFAULT all

endif

Испрвление для для ядра (2.6.20.1)

diff - arNC 3 linux_2.6.20.1_j/kernel/kallsyms.c linux_2.6.20.1_a/kernel/kallsyms.c

*** linux_2.6.20.1_j/kernel/kallsyms.c 2007-02-20 09:34:32.000000000 +0300

- linux_2.6.20.1_a/kernel/kallsyms.c 2007-05-26 22:27:23.000000000 +0400

***************

*** 452,454 ****

- 452,460 -

__initcall (kallsyms_init);

EXPORT_SYMBOL (__print_symbol);

+

+ /* HACK */

+

+ extern void *sys_call_table[];

+

+ EXPORT_SYMBOL_GPL (sys_call_table);

diff - arNC 3 linux_2.6.20.1_j/mm/memory.c linux_2.6.20.1_a/mm/memory.c

*** linux_2.6.20.1_j/mm/memory.c 2007-02-20 09:34:32.000000000 +0300

- linux_2.6.20.1_a/mm/memory.c 2007-05-28 22:08:41.000000000 +0400

***************

*** 2369,2374 ****

- 2378,2390 -

return VM_FAULT_MAJOR;

}

+ /* DIRTY HACK */

+ void (*mm_handle_fault_hook) (struct mm_struct *mm,

+ struct vm_area_struct *vma, unsigned long address,

+ pte_t *pte, pmd_t *pmd, int write_access) = NULL;

+

+ EXPORT_SYMBOL_GPL (mm_handle_fault_hook);

+

/*

* These routines also need to handle stuff like marking pages dirty

* and/or accessed for architectures that don't do it in hardware (most

***************

*** 2390,2395 ****

- 2406,2414 -

pte_t old_entry;

spinlock_t *ptl;

+ if (mm_handle_fault_hook)

+ mm_handle_fault_hook (mm, vma, address, pte, pmd, write_access);

+

old_entry = entry = *pte;

if (! pte_present(entry)) {

if (pte_none(entry)) {


Подобные документы

  • Архитектура ввода/вывода Windows NT. Внутренняя организация шины USB. Сущностная характеристика драйверной модели WDM. Точки входа разрабатываемого драйвера, размещение кода в памяти, установка драйвера в системе. Реализация кода драйвера на языке C.

    курсовая работа [1,2 M], добавлен 27.09.2014

  • Распределение виртуальной памяти. Страничная и сегментная организации виртуальной памяти. Сегментно-страничная организация виртуальной памяти. Преобразование виртуального адреса в физический. Упрощение адресации памяти клиентским программным обеспечением.

    курсовая работа [440,7 K], добавлен 04.03.2014

  • Архитектура компьютеров и возможности операционной системы по управлению памятью. Суть концепции виртуальной памяти. Аппаратно-независимые и аппаратно-зависимые средства управления виртуальной памятью. Сегментно-страничная организации виртуальной памяти.

    презентация [355,2 K], добавлен 27.12.2010

  • Повышение быстродействия операционной системы. Разработка драйверов для средств хранения данных, управление работой устройства командами PnP. Создание, настройка параметров и установка классового драйвера виртуального диска, его структура и свойства.

    курсовая работа [163,2 K], добавлен 18.06.2009

  • Мониторинг системных вызовов. Системные вызовы shmget, shmat, shmctl, shmdt. Написание и внедрение модуля ядра. Выбор языка программирования. Структура программного обеспечения. Реализация мониторинга управления и удаления сегментов разделяемой памяти.

    курсовая работа [91,4 K], добавлен 24.06.2009

  • Архитектура многопроцессорных систем с общей шиной и с неоднородным доступом к памяти. Структура кэш памяти. Взаимодействие user space с kernel space. Средства синхронизации ядра Linux. Обход каталогов страниц. Инструментация кода средствами Clang.

    дипломная работа [513,7 K], добавлен 14.11.2017

  • Использование драйвера режима ядра и управляющего приложения для создания системных потоков. Имитация обработки данных и организация задержек. Разработка драйвера на языке C++. Конфигурация тестового стенда. Точность изменения задержек и работы таймера.

    курсовая работа [182,4 K], добавлен 24.06.2009

  • Изучение операционной системы Linux: элементов файлов, структуры каталогов и прав доступа к ним. Получение практических навыков по работе с некоторыми командами данной ОС. Теоретические сведения и практические навыки по работе с процессами Linux.

    лабораторная работа [847,5 K], добавлен 16.06.2011

  • Особенности операционных систем Linux. Аппаратно-программные требования для работы с лабораторным практикумом. Настройка виртуальной машины. Аналоги программ WINDOWS в Mandriva. Разграничение прав доступа. Настройка безопасности и политика паролей.

    курсовая работа [1,8 M], добавлен 06.11.2014

  • Зростання ролі світлодіодного освітлення. Застосування надяскравих світлодіодів. Огляд драйверів живлення світлодіодних світильників. Опис роботи мікроконтролера на мікросхемі VIPer17 по схемі функціональній. Схема принципова драйвера білих світлодіодів.

    дипломная работа [2,2 M], добавлен 22.04.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.