Мониторинг виртуальной памяти в ОС 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