Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions 07-MemoryManagement/kernel_space/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

obj-m += memory_manag_kernel.o

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

all:
make -C $(BUILD_KERNEL) M=$(PWD) modules
clean:
make -C $(BUILD_KERNEL) M=$(PWD) clean
346 changes: 346 additions & 0 deletions 07-MemoryManagement/kernel_space/memory_manag_kernel.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,346 @@
// SPDX-License-Identifier: GPL
#include <linux/init.h> // Macros used to mark up functions __init __exit
#include <linux/module.h> // Core header for loading LKMs into the kernel
#include <linux/kernel.h> // Contains types, macros, functions for the kernel
#include <linux/types.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/jiffies.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
#include <linux/time.h>

typedef void *(*memory_allocate) (ssize_t size, void *context);
typedef void (*memory_free) (const void *mem, void *context);
typedef size_t (*memory_incr_size)(const size_t cur_size);

struct cnf_mem_allocate {
memory_allocate mem_allocate;
void *cnt;
};

struct cnf_mem_free {
memory_free mem_free;
void *cnt;
};

struct mem_config {
struct cnf_mem_allocate cnf_allocate;
struct cnf_mem_free cnf_free;
memory_incr_size incr_size;
size_t start_size;
size_t max_size_mem;
};

struct mem_description {
struct mem_config config;
char *buf;
size_t size_buf;
};

static long long get_timeout(struct timespec start, struct timespec end)
{
struct timespec sub = timespec_sub(end, start);

return timespec_to_ns(&sub);
}

static void mem_test(struct mem_description *descr)
{
struct timespec ts_start;
struct timespec ts_end;

long long time_spent_allocate;
long long time_spent_free;

size_t size = descr->config.start_size;
int32_t numb_sample = 0;
void *res_allocate;

sprintf(descr->buf + strlen(descr->buf),
"number addr size alloc(ns) free(ns)\n");

while (size < descr->config.max_size_mem) {
numb_sample++;

getnstimeofday(&ts_start);
res_allocate = descr->config.cnf_allocate.mem_allocate(size,
descr->config.cnf_allocate.cnt);
getnstimeofday(&ts_end);
time_spent_allocate = get_timeout(ts_start, ts_end);


if (res_allocate != NULL) {
getnstimeofday(&ts_start);
descr->config.cnf_free.mem_free(res_allocate,
descr->config.cnf_free.cnt);
getnstimeofday(&ts_end);
time_spent_free = get_timeout(ts_start, ts_end);
} else {
time_spent_free = 0;
}

sprintf(descr->buf + strlen(descr->buf),
" %4u %8p %-10u%10llu %10llu\n",
numb_sample, res_allocate, size,
time_spent_allocate, time_spent_free);
size = descr->config.incr_size(size);
}
}

static size_t incr_shift_bit(size_t cur_size)
{
return (cur_size << 1);
}

struct cnt_kmalloc {
gfp_t flags;
};

static void *mem_kmalloc(ssize_t size, struct cnt_kmalloc *cnt)
{
return kmalloc(size, cnt->flags);
}

static void mem_kfree(const void *mem, void *context)
{
kfree(mem);
}

static ssize_t test_kmalloc_show(struct class *class,
struct class_attribute *attr, char *buf)
{

struct mem_description descr;
struct cnt_kmalloc cnt;

cnt.flags = GFP_KERNEL;

descr.config.cnf_allocate.mem_allocate = (memory_allocate)mem_kmalloc;
descr.config.cnf_allocate.cnt = (void *)&cnt;

descr.config.cnf_free.mem_free = mem_kfree;
descr.config.cnf_free.cnt = NULL;

descr.config.incr_size = incr_shift_bit;

descr.buf = buf;
descr.config.max_size_mem = 0x9000000;
descr.config.start_size = 1;

sprintf(descr.buf + strlen(descr.buf), "kmalloc:\n");
mem_test(&descr);


return strlen(buf);
}



static void *mem_kzalloc(ssize_t size, struct cnt_kmalloc *cnt)
{
return kzalloc(size, cnt->flags);
}

static void mem_kzfree(const void *mem, void *context)
{
kzfree(mem);
}

static ssize_t test_kzalloc_show(struct class *class,
struct class_attribute *attr, char *buf)
{

struct mem_description descr;
struct cnt_kmalloc cnt;

cnt.flags = GFP_KERNEL;

descr.config.cnf_allocate.mem_allocate = (memory_allocate)mem_kzalloc;
descr.config.cnf_allocate.cnt = (void *)&cnt;

descr.config.cnf_free.mem_free = mem_kzfree;
descr.config.cnf_free.cnt = NULL;

descr.config.incr_size = incr_shift_bit;

descr.buf = buf;
descr.config.max_size_mem = 0x9000000;
descr.config.start_size = 1;

sprintf(descr.buf + strlen(descr.buf), "kzmalloc:\n");
mem_test(&descr);


return strlen(buf);
}


static void *mem_vmalloc(ssize_t size, void *cnt)
{
return vmalloc(size);
}

static void mem_vfree(const void *mem, void *context)
{
vfree(mem);
}

static ssize_t test_vmalloc_show(struct class *class,
struct class_attribute *attr, char *buf)
{
struct mem_description descr;

descr.config.cnf_allocate.mem_allocate = (memory_allocate)mem_vmalloc;
descr.config.cnf_allocate.cnt = NULL;

descr.config.cnf_free.mem_free = mem_vfree;
descr.config.cnf_free.cnt = NULL;

descr.config.incr_size = incr_shift_bit;

descr.buf = buf;
descr.config.max_size_mem = 0x9000000;
descr.config.start_size = 1;

sprintf(descr.buf + strlen(descr.buf), "vmalloc:\n");
mem_test(&descr);


return strlen(buf);
}

struct mem_free_page_cnt {
gfp_t flags;
unsigned long page;
unsigned int order;
};

static size_t incr_page(size_t cur_size)
{
return cur_size + PAGE_SIZE;
}

static void *mem_get_fre_page(ssize_t size, struct mem_free_page_cnt *cnt)
{
cnt->order = size % PAGE_SIZE == 0 ?
size / PAGE_SIZE : size / PAGE_SIZE + 1;
cnt->page = __get_free_pages(cnt->flags, cnt->order);
return (void *)(cnt->page);
}

static void mem_free_pages(const void *mem, struct mem_free_page_cnt *cnt)
{
free_pages(cnt->page, cnt->order);
}


static ssize_t test_get_free_page_show(struct class *class,
struct class_attribute *attr, char *buf)
{

struct mem_description descr;
struct mem_free_page_cnt cnt;

cnt.flags = GFP_KERNEL;

descr.config.cnf_allocate.mem_allocate =
(memory_allocate)mem_get_fre_page;

descr.config.cnf_allocate.cnt = (void *)&cnt;

descr.config.cnf_free.mem_free = (memory_free)mem_free_pages;
descr.config.cnf_free.cnt = (void *)&cnt;

descr.config.incr_size = incr_page;

descr.buf = buf;
descr.config.max_size_mem = PAGE_SIZE*29;
descr.config.start_size = PAGE_SIZE;

sprintf(descr.buf + strlen(descr.buf), "get_free_page:\n");
mem_test(&descr);


return strlen(buf);
}


struct class_attribute attr_test_kmalloc = {
.attr = { .name = "test_kmalloc", .mode = 0444 },
.show = test_kmalloc_show,
};

struct class_attribute attr_test_kzmalloc = {
.attr = { .name = "test_kzmalloc", .mode = 0444 },
.show = test_kzalloc_show,
};

struct class_attribute attr_test_vmalloc = {
.attr = { .name = "test_vmalloc", .mode = 0444 },
.show = test_vmalloc_show,
};

struct class_attribute attr_test_free_page = {
.attr = { .name = "test_get_free_page", .mode = 0444 },
.show = test_get_free_page_show,
};


static struct class *mem_class;

static int __init mem_init(void)
{
int ret;

mem_class = class_create(THIS_MODULE, "memory_management");
if (mem_class == NULL) {
pr_err("MemoryManagement: error creating sysfs class\n");
return -ENOMEM;
}

ret = class_create_file(mem_class, &attr_test_kmalloc);
if (ret) {
pr_err("MemoryManagement: error creating sysfs class attribute\n");
return ret;
}

ret = class_create_file(mem_class, &attr_test_kzmalloc);
if (ret) {
pr_err("MemoryManagement: error creating sysfs class attribute\n");
return ret;
}

ret = class_create_file(mem_class, &attr_test_vmalloc);
if (ret) {
pr_err("MemoryManagement: error creating sysfs class attribute\n");
return ret;
}

ret = class_create_file(mem_class, &attr_test_free_page);
if (ret) {
pr_err("MemoryManagement: error creating sysfs class attribute\n");
return ret;
}

pr_info("MemoryManagement:loaded\n");
return 0;
}

static void __exit mem_exit(void)
{
class_remove_file(mem_class, &attr_test_kmalloc);
class_remove_file(mem_class, &attr_test_kzmalloc);
class_remove_file(mem_class, &attr_test_vmalloc);
class_remove_file(mem_class, &attr_test_free_page);
class_destroy(mem_class);
pr_info("MemoryManagement: closed");
}

module_init(mem_init);
module_exit(mem_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Happybolt <dmytro.topikha@gmail.com>");
MODULE_DESCRIPTION("MemoryManagement");
MODULE_VERSION("0.1");
33 changes: 33 additions & 0 deletions 07-MemoryManagement/kernel_space/result/kmalloc
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
$ cat /sys/class/memory_management/test_kmalloc
kmalloc:
number addr size alloc(ns) free(ns)
1 c70a22a8 1 2747 1714
2 c70a22a8 2 1005 508
3 c70a22a8 4 537 441
4 c70a22a8 8 510 398
5 c7802320 16 630 464
6 c71ec0c0 32 519 439
7 c71d3000 64 615 421
8 c71de500 128 581 379
9 c7babc00 256 715 1436
10 c71dd400 512 823 425
11 c71f0400 1024 1941 380
12 c70cf800 2048 1149 459
13 c7919000 4096 1097 445
14 c7072000 8192 1645 432
15 c7204000 16384 10028 6274
16 c7208000 32768 2978 1700
17 c7210000 65536 1829 1382
18 c7220000 131072 2098 1468
19 c7240000 262144 2669 2768
20 c7280000 524288 4116 3430
21 c7300000 1048576 6888 5726
22 c6800000 2097152 14032 9778
23 c6800000 4194304 23305 17540
24 (null) 8388608 19950 0
25 (null) 16777216 8017 0
26 (null) 33554432 25207 0
27 (null) 67108864 26982 0
28 (null) 134217728 37757 0


Loading