关于linux 内核抢占的实验
实验背景
在一个路由器的项目中,使用的是AR9344 平台,linux系统,经常遇到系统卡死情况,后来打开内核抢占,虽然没有根本解决问题,但系统卡死的现象得到了很大的改善。想更加了解下内核抢占,所以就做了如下的实验,来研究下。
linux的任务调度简介
首先简单了解下linux的任务调度。
目的:更加合理的分配cpu资源,让每个程序都能有机会运行,让优先级更高的程序优先运行。
内容:主要包括调度算法和上下文的保存和切换,说白了就是选择哪个进程作为下一个执行进程,然后就是怎么切换到该进程。
调度时机:
(1) 调用cond_resched()时
(2) 显式调用schedule()时
(3) 从系统调用或者异常中断返回用户空间时
(4) 从中断上下文返回用户空间时
(5) 内核抢占开启,高优先级内核态程序抢占其他程序
实验的基本思路
1 AR9344是单核cpu,linux 内核版本是2.6,内核支持配置内核抢占。
2 编写一个用户程序,循环打印。
3 编写一个内核驱动,在write函数中也进行循环打印,可以通过设备节点调用到该write函数,从而进入内核循环打印状态。
4 同时观察串口的打印和串口输入。
5 同时观察按键中断和网线的插拔中断的打印。
6 对比开启和关闭内核抢占的情况下以上的现象。
实验步骤
1 打开9344 的内核抢占
修改 arch/mips/configs/db12x_defconfig 文件
161 CONFIG_PREEMPT_NONE=y
162 # CONFIG_PREEMPT_VOLUNTARY is not set
163 #CONFIG_PREEMPT is not set
改为,打开内核抢占
161 #CONFIG_PREEMPT_NONE=y
162 # CONFIG_PREEMPT_VOLUNTARY is not set
163 CONFIG_PREEMPT=y
修改完成后,编译,烧写,重启。
2 编写用户程序
编写了shell脚本moon.sh,其中循环打印,内容如下:
#!/bin/sh
while [ 1 -le 5 ]
do
echo moon
sleep 3
done
3 编写内核驱动
编写wifi_test.c 驱动文件,为char驱动,其中只是在write函数中循环打印,相关代码如下:
68 static int thread_process(void* param)
69 {
70 int i;
71 for (i = 0; i < 20; i++)
72 {
73 mdelay(5000);
74
75 printk("hello kernel pthread\n");
76
77 }
78 return 0;
79 };
80
4 同时运行用户程序和内核驱动
加载编好的驱动, 创建设备文件, 运行 moon.sh,会看到一直打印moon。 之后运行
echo kk > /dev/wifitest //wifitest为设备文件,通过系统调用,运行刚才的内核驱动。
观察开启内核抢占和关闭内核抢占的现象对比
实验结果
1 不开抢占:
系统一直打印
hello kernel pthread
不在打印moon 。 并且串口输入不启作用。说明系统调用后一直在kernnel中循环,其他进程不在执行。
但按键中断和网口中断能相应,可以看到按键中断的打印。
2 开抢占:
系统交叉打印
hello kernel pthread
moon
并且串口可以输入,按键中断可以响应,说明抢占打开后,内核态的进程循环不会独占cpu了。当内核态进程循环打印的过程总调用睡眠时,会被其他进程抢占。