mem = kmalloc(4096 * sizeof(*mem), GFP_KERNEL); if (mem == NULL) goto err_mem;
pr_info("chars: "); for (i = 0; i < 4096; i++) { if (isalpha(mem[i])) printk(KERN_CONT "%c ", mem[i]); } pr_info("\n");
return0;
err_mem: return-1; }
staticvoidmem_exit(void) { kfree(mem); }
module_init(mem_init); module_exit(mem_exit);
结果如下:(printk 默认换行,可以使用 KERN_CONT 禁止换行)
1 2 3 4 5 6 7 8 9 10
mem: loading out-of-tree module taints kernel. chars: Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z Z
MODULE_DESCRIPTION("Sleep while atomic"); MODULE_AUTHOR("SO2"); MODULE_LICENSE("GPL");
staticintsched_spin_init(void) { spinlock_t lock;
spin_lock_init(&lock);
/* TODO 0: Use spin_lock to aquire the lock */ spin_lock(&lock); set_current_state(TASK_INTERRUPTIBLE); /* Try to sleep for 5 seconds. */ schedule_timeout(5 * HZ);
/* TODO 0: Use spin_unlock to release the lock */ spin_unlock(&lock); return0; }
/* TODO 1: allocated and initialize a task_info struct */ ti = (struct task_info*)kmalloc(sizeof(struct task_info),NULL); ti->pid = pid; ti->timestamp = jiffies; return ti; }
staticintmemory_init(void) { structtask_struct *p; /* TODO 2: call task_info_alloc for current pid */ p = current; ti1 = task_info_alloc(p->pid); /* TODO 2: call task_info_alloc for parent PID */ p = current->parent; ti2 = task_info_alloc(p->pid); /* TODO 2: call task_info alloc for next process PID */ p = next_task(p); ti3 = task_info_alloc(p->pid); /* TODO 2: call task_info_alloc for next process of the next process */ p = next_task(next_task(p)); ti4 = task_info_alloc(p->pid); return0; }
staticvoidmemory_exit(void) { /* TODO 3: print ti* field values */ printk("%d:%d",ti1->pid,ti1->timestamp); printk("%d:%d",ti2->pid,ti1->timestamp); printk("%d:%d",ti3->pid,ti1->timestamp); printk("%d:%d",ti4->pid,ti1->timestamp); /* TODO 4: free ti* structures */ kfree(ti1); kfree(ti2); kfree(ti3); kfree(ti4); }
/* TODO 1: Allocate task_info and add it to list */ ti = task_info_alloc(pid); list_add(&ti->list,&head); }
staticvoidtask_info_add_for_current(void) { /* Add current, parent, next and next of next to the list */ task_info_add_to_list(current->pid); task_info_add_to_list(current->parent->pid); task_info_add_to_list(next_task(current)->pid); task_info_add_to_list(next_task(next_task(current))->pid); }
/* TODO 2: Iterate over the list and delete all elements */ list_for_each_safe(p, tmp, &head) { ti = list_entry(p, struct task_info, list); list_del(p); kfree(ti); } }
/* TODO 1: Look for pid and return task_info or NULL if not found */ list_for_each(p, &head) { ti = list_entry(p, struct task_info, list); if(ti->pid == pid){ return ti; } } returnNULL; }
/* TODO 2: Ensure that at least one task is not deleted */ ti = task_info_find_pid(current->parent->pid); if(ti == NULL){ printk("not find pid: %d",ti->pid); } else{ printk("find pid: %d",ti->pid); } list_del(&ti->list); task_info_remove_expired(); list_add(&ti->list, &head); task_info_print_list("after removing expired"); task_info_purge_list(); task_info_remove_expired(); }
/* TODO 1: Protect list, is this read or write access? */ spin_lock(&lock); ti = task_info_find_pid(pid); if (ti != NULL) { ti->timestamp = jiffies; atomic_inc(&ti->count); /* TODO: Guess why this comment was added here */ return; } spin_unlock(&lock); /* TODO 1: critical section ends here */
ti = task_info_alloc(pid); /* TODO 1: protect list access, is this read or write access? */ spin_lock(&lock); list_add(&ti->list, &head); spin_unlock(&lock); /* TODO 1: critical section ends here */ }
voidtask_info_add_for_current(void) { task_info_add_to_list(current->pid); task_info_add_to_list(current->parent->pid); task_info_add_to_list(next_task(current)->pid); task_info_add_to_list(next_task(next_task(current))->pid); } EXPORT_SYMBOL(task_info_add_for_current); /* TODO 2: Export the kernel symbol */
/* TODO 1: Protect list, is this read or write access? */ spin_lock(&lock); list_for_each(p, &head) { ti = list_entry(p, struct task_info, list); pr_info("(%d, %lu) ", ti->pid, ti->timestamp); } spin_unlock(&lock); /* TODO 1: Critical section ends here */ pr_info("]\n"); } EXPORT_SYMBOL(task_info_print_list); /* TODO 2: Export the kernel symbol */
/* TODO 1: Protect list, is this read or write access? */ spin_lock(&lock); list_for_each_safe(p, q, &head) { ti = list_entry(p, struct task_info, list); if (jiffies - ti->timestamp > 3 * HZ && atomic_read(&ti->count) < 5) { list_del(p); kfree(ti); } } spin_unlock(&lock); /* TODO 1: Critical section ends here */ } EXPORT_SYMBOL(task_info_remove_expired); /* TODO 2: Export the kernel symbol */
/* TODO 1: Protect list, is this read or write access? */ spin_lock(&lock); list_for_each_safe(p, q, &head) { ti = list_entry(p, struct task_info, list); list_del(p); kfree(ti); } spin_unlock(&lock); /* TODO 1: Critical sections ends here */ }
staticintlist_test_init(void) { /* TODO 1: Uncomment after exporting the symbols in 6-list-sync. */ task_info_add_for_current(); task_info_print_list("after new addition");
return0; }
staticvoidlist_test_exit(void) { /* TODO 1: Uncomment after exporting the symbols in 6-list-sync. */ task_info_remove_expired(); task_info_print_list("after removing expired"); }