myfather103的专栏

第一章 环境

Ubuntu 14.10

Linux Kernel 3.18.6

第二章 代码及调试过程

环境搭建与内核准备:

cd ~/LinuxKernel/wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xzxz -d linux-3.18.6.tar.xztar -xvf linux-3.18.6.tarcd linux-3.18.6make i386_defconfigmake cd ~/LinuxKernel/mkdir rootfsgit clone https://github.com/mengning/menu.gitcd menugcc -o init linktable.c menu.c test.c -m32 -static –lpthreadcd ../rootfscp ../menu/init ./find . | cpio -o -Hnewc |gzip -9 > ../rootfs.imgcd ~/LinuxKernel/qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img重新编译内核:make menuconfigkernel hacking—>compile-time checks and compile options[*] compile the kernel with debug info开始调试:qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 同时另开一个窗口,运行GDB:gdb(gdb)file linux-3.18.6/vmlinux (gdb)target remote:1234 (gdb)break start_kernel(gdb)list这一次代码就不贴出来了,在init/mian.c下,主要是代码太长。

单击相应的链接可以找到引用的变量位置,,我下载了几个。

这里打算分析:

cpu_startup_entry

page_address_init()

rest_init()

page_alloc_init()

trap_init()

tick_init()

profile_init()

key_init()

security_init()

buffer_init()

init_task 0号进程

run_init_process(const char *init_filename) 1号进程

0号进程init_task的结构:

#define INIT_TASK(tsk)\{\.state= 0,\.stack= &init_thread_info,\.usage= ATOMIC_INIT(2),\.flags= PF_KTHREAD,\.prio= MAX_PRIO-20,\.static_prio= MAX_PRIO-20,\.normal_prio= MAX_PRIO-20,\.policy= SCHED_NORMAL,\.cpus_allowed= CPU_MASK_ALL,\.nr_cpus_allowed= NR_CPUS,\.mm= NULL,\.active_mm= &init_mm,\.se= {\.group_node = LIST_HEAD_INIT(tsk.se.group_node),\},\.rt= {\.run_list= LIST_HEAD_INIT(tsk.rt.run_list),\.time_slice= RR_TIMESLICE,\},\.tasks= LIST_HEAD_INIT(tsk.tasks),\INIT_PUSHABLE_TASKS(tsk)\INIT_CGROUP_SCHED(tsk)\.ptraced= LIST_HEAD_INIT(tsk.ptraced),\.ptrace_entry= LIST_HEAD_INIT(tsk.ptrace_entry),\.real_parent= &tsk,\.parent= &tsk,\.children= LIST_HEAD_INIT(tsk.children),\.sibling= LIST_HEAD_INIT(tsk.sibling),\.group_leader= &tsk,\RCU_POINTER_INITIALIZER(real_cred, &init_cred),\RCU_POINTER_INITIALIZER(cred, &init_cred),\.comm= INIT_TASK_COMM,\.thread= INIT_THREAD,\.fs= &init_fs,\.files= &init_files,\.signal= &init_signals,\.sighand= &init_sighand,\.nsproxy= &init_nsproxy,\.pending= {\.list = LIST_HEAD_INIT(tsk.pending.list),\.signal = {{0}}},\.blocked= {{0}},\.alloc_lock= __SPIN_LOCK_UNLOCKED(tsk.alloc_lock),\.journal_info= NULL,\.cpu_timers= INIT_CPU_TIMERS(tsk.cpu_timers),\.pi_lock= __RAW_SPIN_LOCK_UNLOCKED(tsk.pi_lock),\.timer_slack_ns = 50000, /* 50 usec default slack */\.pids = {\[PIDTYPE_PID] = INIT_PID_LINK(PIDTYPE_PID),\[PIDTYPE_PGID] = INIT_PID_LINK(PIDTYPE_PGID),\[PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID),\},\.thread_group= LIST_HEAD_INIT(tsk.thread_group),\.thread_node= LIST_HEAD_INIT(init_signals.thread_head),\INIT_IDS\INIT_PERF_EVENTS(tsk)\INIT_TRACE_IRQFLAGS\INIT_LOCKDEP\INIT_FTRACE_GRAPH\INIT_TRACE_RECURSION\INIT_TASK_RCU_PREEMPT(tsk)\INIT_TASK_RCU_TASKS(tsk)\INIT_CPUSET_SEQ(tsk)\INIT_RT_MUTEXES(tsk)\INIT_VTIME(tsk)\}第三章 调试

设置断点:一共13个。

命令为:

(gdb)break <function name>接着输入c进行调试。

流程如下:

来几张有代表性的调试图片:

start_kernel:

page_address_init:

buffer_init:

security_init:

cpu_startup_entry:

run_init_process:

第四章 总结

通过这个方式我们知道了,Linux内核通过调用那些函数来启动,看起来在启动的时候只有些跳动的字符,可是在内部是很忙碌的。希望以后能了解到每一个函数的具体作用。不过,这就非常困难的了。

set_task_stack_end_magic确立一个init_task,这个便是后来的0号进程,也就是idle。

通过参考资料:

通过检测时钟中断来提醒idle进程来复制自己的进程信息,来创建一个进程。就好像之前的myKernel一样。

然后idle进程就会检测,如果有新的任务便会中断运行,生成并释放系统资源让进程使用。当进程结束,系统便将资源收回返回给idle进程。

当执行到run_init_process时,1号进程便开始运行。

附录

卢晅+ 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程

他们比任何人都分毫较量,又比任何人都口是心非。他们比任何人都依赖彼此,

myfather103的专栏

相关文章:

你感兴趣的文章:

标签云: