YSU System HW2

Creator
Creator
Seonglae ChoSeonglae Cho
Created
Created
2023 Nov 29 7:47
Editor
Edited
Edited
2023 Dec 17 17:49
Refs
Refs
make sudo rmmod hw2 sudo insmod hw2.ko cat /proc/hw2
커널 모듈만 작성하면 되고 컴파일 할필요 없다
#include <asm/io.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/time.h> // Constants #define PROC_NAME "hw2" #define MAX_TRACES 5 #define PERIOD 10 #define DELAY (PERIOD * HZ) // Macros MODULE_AUTHOR("Jo, Alan"); MODULE_LICENSE("GPL"); DEFINE_SPINLOCK(hw2_lock); // Memory info structure struct memory_info { pid_t process_id; char command[TASK_COMM_LEN]; unsigned long page_directory; long int uptime; // Virtual unsigned long start_code; unsigned long end_code; unsigned long start_data; unsigned long end_data; unsigned long start_heap; unsigned long end_heap; unsigned long start_stack; unsigned long end_stack; unsigned long start_time; // Physical unsigned long physical_start_code; unsigned long physical_end_code; unsigned long physical_start_data; unsigned long physical_end_data; unsigned long physical_start_heap; unsigned long physical_end_heap; unsigned long physical_start_stack; unsigned long physical_end_stack; // Physical unsigned long pgd_start; unsigned long pud_start; unsigned long pmd_start; unsigned long pte_start; unsigned long pgd_start_val; unsigned long pud_start_val; unsigned long pmd_start_val; unsigned long pte_start_val; unsigned long pgd_end; unsigned long pud_end; unsigned long pmd_end; unsigned long pte_end; unsigned long pgd_end_val; unsigned long pud_end_val; unsigned long pmd_end_val; unsigned long pte_end_val; }; // Global variables struct memory_info *memory_info_array; struct timer_list timer; unsigned long int module_start_jiffies; int record_count = 0; // Print bar void print_bar(struct seq_file *s) { seq_printf(s, "--------------------------------------------------\n"); } // Print address translation void print_address(struct seq_file *s, struct memory_info *m, int i) { if (m) { print_bar(s); seq_printf(s, "[Trace #%d]\n", i); seq_printf(s, "Uptime (s): %d\n", m->uptime); seq_printf(s, "Command: %s\n", m->command); seq_printf(s, "PID: %d\n", m->process_id); seq_printf(s, "Start time (s): %d\n", m->start_time); seq_printf(s, "PGD base address: 0x%lx\n", m->page_directory); seq_printf(s, "Code Area\n"); seq_printf(s, "- start (virtual): 0x%lx\n", m->start_code); seq_printf(s, "- start (PGD): 0x%lx, 0x%lx\n", m->pgd_start, m->pgd_start_val); seq_printf(s, "- start (PUD): 0x%lx, 0x%lx\n", m->pud_start, m->pud_start_val); seq_printf(s, "- start (PMD): 0x%lx, 0x%lx\n", m->pmd_start, m->pmd_start_val); seq_printf(s, "- start (PTE): 0x%lx, 0x%lx\n", m->pte_start, m->pte_start_val); seq_printf(s, "- start (physical): 0x%lx\n", m->physical_start_code, m->page_directory); seq_printf(s, "- end (virtual): 0x%lx\n", m->end_code); seq_printf(s, "- end (PGD): 0x%lx, 0x%lx\n", m->pgd_end, m->pgd_end_val); seq_printf(s, "- end (PUD): 0x%lx, 0x%lx\n", m->pud_end, m->pud_end_val); seq_printf(s, "- end (PMD): 0x%lx, 0x%lx\n", m->pmd_end, m->pmd_end_val); seq_printf(s, "- end (PTE): 0x%lx, 0x%lx\n", m->pte_end, m->pte_end_val); seq_printf(s, "- end (physical): 0x%lx\n", m->physical_end_code, m->page_directory); seq_printf(s, "Data Area\n"); seq_printf(s, "- start (virtual): 0x%lx\n", m->start_data); seq_printf(s, "- end (virtual): 0x%lx\n", m->end_data); seq_printf(s, "- start (physical): 0x%lx\n", m->physical_start_data, m->page_directory); seq_printf(s, "- end (physical): 0x%lx\n", m->physical_end_data, m->page_directory); seq_printf(s, "Heap Area\n"); seq_printf(s, "- start (virtual): 0x%lx\n", m->start_heap); seq_printf(s, "- end (virtual): 0x%lx\n", m->end_heap); seq_printf(s, "- start (physical): 0x%lx\n", m->physical_start_heap, m->page_directory); seq_printf(s, "- end (physical): 0x%lx\n", m->physical_end_heap, m->page_directory); seq_printf(s, "Stack Area\n"); seq_printf(s, "- start (virtual): 0x%lx\n", m->start_stack); seq_printf(s, "- end (virtual): 0x%lx\n", m->end_stack); seq_printf(s, "- start (physical): 0x%lx\n", m->physical_start_stack, m->page_directory); seq_printf(s, "- end (physical): 0x%lx\n", m->end_stack, m->physical_end_stack); } } // Handle proc read void handle_proc_read(struct seq_file *s) { spin_lock_irq(&hw2_lock); // Print header seq_printf(s, "[System Programming Assignment #2]\n"); seq_printf(s, "ID: %s\n", "2017143020"); seq_printf(s, "Name: %s\n", "Cho, Seonglae"); seq_printf(s, "Uptime (s): %d\n", jiffies_to_msecs(get_jiffies_64()) / 1000 - jiffies_to_msecs(module_start_jiffies) / 1000); // Print 5 memory_info for (int i = 0; i < record_count; i++) { struct memory_info *current_memory_info = &memory_info_array[i]; print_address(s, current_memory_info, i); } print_bar(s); spin_unlock_irq(&hw2_lock); } static void *hw2_seq_start(struct seq_file *s, loff_t *pos) { static unsigned long counter = 0; if (*pos == 0) return &counter; else { *pos = 0; return NULL; } } static void *hw2_seq_next(struct seq_file *s, void *v, loff_t *pos) { unsigned long *tmp_v = (unsigned long *)v; (*tmp_v)++; (*pos)++; return NULL; } static void hw2_seq_stop(struct seq_file *s, void *v) {} static int hw2_seq_show(struct seq_file *s, void *v) { handle_proc_read(s); return 0; } static struct seq_operations hw2_seq_ops = {.start = hw2_seq_start, .next = hw2_seq_next, .stop = hw2_seq_stop, .show = hw2_seq_show}; static int hw2_proc_open(struct inode *inode, struct file *file) { return seq_open(file, &hw2_seq_ops); } static const struct proc_ops hw2_proc_ops = {.proc_open = hw2_proc_open, .proc_read = seq_read, .proc_lseek = seq_lseek, .proc_release = seq_release}; void probe_proc_memory_info(struct timer_list *timer) { spin_lock_irq(&hw2_lock); rcu_read_lock(); struct task_struct *latest_task = NULL; unsigned long latest_start_time = 0; struct task_struct *task; for_each_process(task) { // Check if kernel-thread if (task->flags & PF_KTHREAD) continue; // Check start time and select the latest task if (task->start_time > latest_start_time) { latest_start_time = task->start_time; latest_task = task; } } if (latest_task) { // Initialize memory_info for the latest task struct mm_struct *mm = latest_task->mm; if (mm) { if (record_count < MAX_TRACES) record_count++; else memmove(memory_info_array, memory_info_array + 1, sizeof(struct memory_info *) * (MAX_TRACES - 1)); struct memory_info *m = &memory_info_array[record_count - 1]; // Store header data m->process_id = latest_task->pid; m->page_directory = mm->pgd; m->start_time = jiffies_to_msecs(nsecs_to_jiffies(latest_task->start_time) - module_start_jiffies) / 1000; strcpy(m->command, latest_task->comm); // Store address data m->start_code = mm->start_code; m->end_code = mm->end_code; m->start_data = mm->start_data; m->end_data = mm->end_data; m->start_heap = mm->start_brk; m->end_heap = mm->brk; m->start_stack = mm->start_stack; m->end_stack = find_vma(mm, mm->start_stack)->vm_end; m->uptime = jiffies_to_msecs(get_jiffies_64()) / 1000 - jiffies_to_msecs(module_start_jiffies) / 1000; // Translate virtual addresses to physical addresses m->physical_start_code = virt_to_phys((void *)mm->start_code); m->physical_end_code = virt_to_phys((void *)mm->end_code); m->physical_start_data = virt_to_phys((void *)mm->start_data); m->physical_end_data = virt_to_phys((void *)mm->end_data); m->physical_start_heap = virt_to_phys((void *)mm->start_brk); m->physical_end_heap = virt_to_phys((void *)mm->brk); m->physical_start_stack = virt_to_phys((void *)mm->start_stack); m->physical_end_stack = virt_to_phys((void *)find_vma(mm, mm->start_stack)->vm_end); pgd_t *pgd_start = pgd_offset_pgd(m->page_directory, m->start_code); p4d_t *p4d_start = p4d_offset(pgd_start, m->start_code); pud_t *pud_start = pud_offset(p4d_start, m->start_code); pmd_t *pmd_start = pmd_offset(pud_start, m->start_code); pte_t *pte_start = pte_offset_kernel(pmd_start, m->start_code); pgd_t *pgd_end = pgd_offset_pgd(m->page_directory, m->end_code); p4d_t *p4d_end = p4d_offset(pgd_end, m->end_code); pud_t *pud_end = pud_offset(p4d_end, m->end_code); pmd_t *pmd_end = pmd_offset(pud_end, m->end_code); pte_t *pte_end = pte_offset_kernel(pmd_end, m->end_code); m->pgd_start = (long unsigned int)pgd_start; m->pud_start = (long unsigned int)pud_start; m->pmd_start = (long unsigned int)pmd_start; m->pte_start = (long unsigned int)pte_start; m->pgd_start_val = pgd_val(*pgd_start); m->pud_start_val = pud_val(*pud_start); m->pmd_start_val = pmd_val(*pmd_start); m->pte_start_val = pte_val(*pte_start); m->pgd_end = (long unsigned int)pgd_end; m->pud_end = (long unsigned int)pud_end; m->pmd_end = (long unsigned int)pmd_end; m->pte_end = (long unsigned int)pte_end; m->pgd_end_val = pgd_val(*pgd_end); m->pud_end_val = pud_val(*pud_end); m->pmd_end_val = pmd_val(*pmd_end); m->pte_end_val = pte_val(*pte_end); } } rcu_read_unlock(); // Setup timer new expire time mod_timer(timer, jiffies + DELAY); spin_unlock_irq(&hw2_lock); } static int __init hw2_init(void) { struct proc_dir_entry *proc_file_entry; proc_file_entry = proc_create(PROC_NAME, 0, NULL, &hw2_proc_ops); module_start_jiffies = get_jiffies_64(); spin_lock_irq(&hw2_lock); // Reserve space for memory_info array up to MAX_PROC tasks memory_info_array = kmalloc(sizeof(struct memory_info *) * MAX_TRACES, GFP_KERNEL); // Setup dynamic timer and probe immediately timer_setup(&timer, probe_proc_memory_info, 0); mod_timer(&timer, jiffies); spin_unlock_irq(&hw2_lock); return 0; } static void __exit hw2_exit(void) { spin_lock_irq(&hw2_lock); // Delete timer & memory_info array del_timer(&timer); kfree(memory_info_array); spin_unlock_irq(&hw2_lock); remove_proc_entry(PROC_NAME, NULL); } module_init(hw2_init); module_exit(hw2_exit);
 
 
 
 
 
 
 

Recommendations