so2学习日志2-内核模块&api


kernel_modules

加载/卸载模块

在虚拟机中可以在kernel_modules下的1-2-test文件夹下尝试

1
2
insmod module.ko
rmmod module.ko

内核oops

内核级错误报告,遇到无法安全处理的操作(空指针引用,非法访问内存,堆栈溢出)时触发,但不会导致内核崩溃,oops记录了错误发生时的系统状态
oops实例分析

内核日志打印
dmesg -c 可以显示并清除当前日志信息
dmesg | tail -10 显示最后10行

模块传参

根据module_param(str, charp, 0000)的声明可对模块进行传参
参数分别对应变量名,变量类型,权限

1
2
3
4
5
6
7
8
9
10
static char *str = "the worm";

module_param(str, charp, 0000);
MODULE_PARM_DESC(str, "A simple string");

static int __init cmd_init(void)
{
pr_info("Early bird gets %s\n", str);
return 0;
}
1
2
3
4
root@qemux86:~/skels/kernel_modules/6-cmd-mod# insmod cmd_mod.ko                
Early bird gets the worm
root@qemux86:~/skels/kernel_modules/6-cmd-mod# insmod cmd_mod.ko str="tired"
Early bird gets tired

kernel_api

控制台日志
0-7对应严重等级

1
2
3
#include<linux/kernel.h>
pr_debug("Hello!\n");
printk(KERN_INFO "Hello2!\n");
1
2
cat /proc/sys/kernel/printk
echo 6 > /proc/sys/kernel/printk

内存分配

1
2
3
4
5
6
#include <linux/slab.h>
string = kmalloc(string_len+1,GFP_KERNEL);
if(!string){
//errer
}
kfree(string);

在原子上下文中睡眠
在原子上下文中,进行阻塞或者睡眠的操作会产生错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static int sched_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);

return 0;
}

如上的代码,会产生错误如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@qemux86:~/skels/kernel_api/2-sched-spin# insmod sched-spin.ko                         
BUG: scheduling while atomic: insmod/279/0x00000002
#0: c4227db8 (&lock){+.+.}-{2:2}, at: sched_spin_init+0x32/0x90 [sched_spin]
Call Trace:
dump_stack+0x6d/0x8b
__schedule_bug.cold+0x65/0x76
__schedule+0x577/0x720
? mark_held_locks+0x3f/0x70
? schedule_timeout+0x172/0x2f0
? _raw_spin_unlock_irqrestore+0x45/0x50
? schedule_timeout+0x172/0x2f0
schedule+0x56/0xd0
schedule_timeout+0x177/0x2f0
? del_timer_sync+0xc0/0xc0
? 0xe0831000
sched_spin_init+0x61/0x90 [sched_spin]
? sched_spin_init+0x32/0x90 [sched_spin]

根据调用栈分析,能定位到错误位置

1
2
3
4
5
sched_spin_init+0x61/0x90 [sched_spin]

schedule_timeout+0x177/0x2f0

schedule+0x56/0xd0

进程pid宏
可以通过 next_task 获取下一个进程的pid

1
2
3
4
ti1 = task_info_alloc(current->pid);
ti2 = task_info_alloc(current->parent->pid);
ti3 = task_info_alloc(next_task(current)->pid);
ti4 = task_info_alloc(next_task(next_task(current))->pid);