环境搭建与配置过程
个人Linux系统环境搭建MenuOS的过程
[toggle hide=“yes” title=“Linux系统环境搭建MenuOS的过程” color=""] 1、Linux系统环境搭建MenuOS的过程
# 下载内核源代码编译内核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 # 一般要编译很长时间,少则20分钟多则数小时
# 制作根文件系统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.img
# 启动MenuOS系统cd ~/LinuxKernel/qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img2、重新配置编译Linux使之携带调试信息 在原来配置的基础上,make menuconfig选中如下选项重新配置Linux,使之携带调试信息
kernel hacking—>[*] compile the kernel with debug infomake重新编译(时间较长) 3、使用gdb跟踪调试内核
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明:# -S freeze CPU at startup (use ’c’ to start execution)# -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项另开一个shell窗口
gdb(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表(gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后[/toggle]
在实验楼中的过程
[toggle hide=“yes” title=“实验楼中实验过程” color=""] 使用实验楼的虚拟机打开shell
cd LinuxKernel/qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img使用gdb跟踪调试内核
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S另开一个shell窗口
gdb(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表(gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后部分步骤如下图所示 [caption id="" align=“aligncenter” width=“308”]
没有-S和-s时[/caption] [caption id="" align=“aligncenter” width=“298”]
有-s和-S时[/caption] [caption id="" align=“aligncenter” width=“286”]
gdb[/caption] [caption id="" align=“aligncenter” width=“284”]
break start_kernel[/caption] [caption id="" align=“aligncenter” width=“277”]
通过list查看break start_kernel后start_kernel前后文代码[/caption] [/toggle]
相关代码分析
start_kernel函数
所在位置:xref: /linux-3.18.6/init/main.c 不管分析内核的哪一部分都会涉及到start_kernel
asmlinkage __visible void __init start_kernel(void){......./*init_task即手工创建的PCB,0号进程就是最终的idle进程*/set_task_stack_end_magic(&init_task);......../*初始化中断向量*/trap_init();/*内存管理模块初始化*/mm_init();/*调度模块初始化*/sched_init();..../*其他初始化*/rest_init()}trap_init();初始化一些中断向量, 主要分析函数所在地址: xref: /linux-3.18.6/arch/x86/kernel/traps.c rest_init();中包含内核启动过程 所在位置:xref: /linux-3.18.6/init/main.c
rest_init()函数
从系统内核一启动,rest_init()会一直存在,是0号进程,并且创建了1号进程,并创建了一些其他的服务进程*/
static noinline void __init_refok rest_init(void){ int pid;
rcu_scheduler_starting(); /* * We need to spawn init first so that it obtains pid 1, however * the init task will end up wanting to create kthreads, which, if * we schedule it before we create kthreadd, will OOPS. */ /*初始化了第一个用户态的进程1号进程*/ kernel_thread(kernel_init, NULL, CLONE_FS); numa_default_policy(); /*创建内核线程管理系统资源 *kthreadd 为内核线程 */ pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); rcu_read_lock(); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); rcu_read_unlock(); complete(&kthreadd_done);
/* * The boot idle thread must execute schedule() * at least once to get things moving: */ init_idle_bootup_task(current); schedule_preempt_disabled(); /* Call into cpu_idle with preempt disabled */ cpu_startup_entry(CPUHP_ONLINE);}kernel_init
原语句:kernel_thread(kernel_init, NULL, CLONE_FS); 所在位置(非语句):xref: /linux-3.18.6/init/main.c 其中主要分析的代码所在的代码段
if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); if (!ret) return 0; pr_err("Failed to execute %s (error %d)n", ramdisk_execute_command, ret);}run_init_process init_process为一号进程,第一个用户态进程
cpu_startup_entry
原语句:cpu_startup_entry(CPUHP_ONLINE); 所在位置(非语句):xref: /linux-3.18.6/kernel/sched/idle.c 其中主要分析的代码
cpu_idle_loop();所在位置(非语句):xref: /linux-3.18.6/kernel/sched/idle.c 主要作用: cpu_idle_loop是一个while(1)循环,当系统没有进程需要执行时就调度到idle进程 其实是0号进程实现部分。 0号进程一直存在,并创建一号进程及其他服务的内核线程。
总结
Linux内核的启动,通过start_kernel()进行各种初始化工作,最终执行到rest_init()来初始化0号进程,同时0号进程创建1号用户态的进程以及其他服务的一些内核线程。然后操作系统就运行起来了。 windCoder原创作品转载请注明出处
参考资料
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
评论