模拟存储程序计算机工作模型一:时钟中断
使用qemu虚拟一个x86 CPU的硬件平台
sudo apt-get install qemu-system-x86
1.下载linux内核代码
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.4.tar.xz
xz -d linux-3.9.4.tar.xz
tar -xvf linux-3.9.4.tar
cd linux-3.9.4
2.修改内核代码
新建目录linux-3.9.4/mykernel
,实现自己的内核模块
修改include/linux/timer.h
// timer.h:254
extern void my_timer_handler(void);
修改arch/x86/kernel/time.c
// time.c:16
#include <linux/timer.h>
// time.c:timer_interrupt():61
my_timer_handler();
// time.c:setup_default_timer_irq():73
printk(KERN_NOTICE "timer interrupt setup\n");
修改include/linux/start_kernel.h
// start_kernel.h:11
extern void __init my_start_kernel(void);
修改init/main.c
// start_kernel.h:start_kernel():643
my_start_kernel();
修改linux3.9.4/Makefile
# Makefile:736
core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ mykernel/
新建mykernel/Makefile
obj-y = mymain.o myinterrupt.o
新建mykernel/myinterrupt.c
#include <linux/kernel_stat.h>
#include <linux/export.h>
#include <linux/interrupt.h>
#include <linux/percpu.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/pid_namespace.h>
#include <linux/notifier.h>
#include <linux/thread_info.h>
#include <linux/time.h>
#include <linux/jiffies.h>
#include <linux/posix-timers.h>
#include <linux/cpu.h>
#include <linux/syscalls.h>
#include <linux/delay.h>
#include <linux/tick.h>
#include <linux/kallsyms.h>
#include <linux/irq_work.h>
#include <linux/sched.h>
#include <linux/sched/sysctl.h>
#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/div64.h>
#include <asm/timex.h>
#include <asm/io.h>
#define CREATE_TRACE_POINTS
#include <trace/events/timer.h>
void my_timer_handler(void) {
printk(KERN_NOTICE "\n>>>>>>>>>>>>>>>>>my_timer_handler here<<<<<<<<<<<<<<<<<<\n\n");
}
新建mykernel/mymain.c
#include <linux/types.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/kernel.h>
#include <linux/syscalls.h>
#include <linux/stackprotector.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/initrd.h>
#include <linux/bootmem.h>
#include <linux/acpi.h>
#include <linux/tty.h>
#include <linux/percpu.h>
#include <linux/kmod.h>
#include <linux/vmalloc.h>
#include <linux/kernel_stat.h>
#include <linux/start_kernel.h>
#include <linux/security.h>
#include <linux/smp.h>
#include <linux/profile.h>
#include <linux/rcupdate.h>
#include <linux/moduleparam.h>
#include <linux/kallsyms.h>
#include <linux/writeback.h>
#include <linux/cpu.h>
#include <linux/cpuset.h>
#include <linux/cgroup.h>
#include <linux/efi.h>
#include <linux/tick.h>
#include <linux/interrupt.h>
#include <linux/taskstats_kern.h>
#include <linux/delayacct.h>
#include <linux/unistd.h>
#include <linux/rmap.h>
#include <linux/mempolicy.h>
#include <linux/key.h>
#include <linux/buffer_head.h>
#include <linux/page_cgroup.h>
#include <linux/debug_locks.h>
#include <linux/debugobjects.h>
#include <linux/lockdep.h>
#include <linux/kmemleak.h>
#include <linux/pid_namespace.h>
#include <linux/device.h>
#include <linux/kthread.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/idr.h>
#include <linux/kgdb.h>
#include <linux/ftrace.h>
#include <linux/async.h>
#include <linux/kmemcheck.h>
#include <linux/sfi.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/perf_event.h>
#include <linux/file.h>
#include <linux/ptrace.h>
#include <linux/blkdev.h>
#include <linux/elevator.h>
#include <asm/io.h>
#include <asm/bugs.h>
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/cacheflush.h>
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/smp.h>
#endif
void __init my_start_kernel(void) {
int i = 0;
while(1) {
i++;
if(i%100000 == 0)
printk(KERN_NOTICE "my_start_kernel here %d \n",i);
}
}
3.编译运行内核
make allnoconfig
make
# 运行
qemu-system-i386 -kernel arch/x86/boot/bzImage
若编译时提示no such file compiler-gcc11.h
mv include/linux/compiler-gcc3.h include/linux/compiler-gcc11.h
linux内核中,内核入口函数为init/main.c:asmlinkage void __init start_kernel(void)
虚拟CPU执行C代码,可以看到mymain.c:my_start_kernel()
在不停地执行
同时有一个中断处理程序的上下文,周期性地产生时钟中断信号,触发myinterrupt.c:my_timer_handler()