一、实验楼实验

1 cd LinuxKernel/
2 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

内核启动完成后进入menu程序,支持三个命令help、version和quit

  • 使用gdb跟踪调试内核

1 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明:
2 # -S freeze CPU at startup (use ’c’ to start execution)
3 # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

  • 另开一个shell窗口
1 gdb
2 (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
3 (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
4 (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

按c后系统开始运行,启动到start_cernel的位置

输入list之后看到执行的位置

再设置一个断点,系统执行到rest_init的位置

二、简单分析一下start_kernel

1、在init目录下main.c里找到start_kernel函数

500asmlinkage __visible void __init start_kernel(void)
501{
502 char *command_line;
503 char *after_dashes;
504
505 /*
506 * Need to run as early as possible, to initialize the
507 * lockdep hash:
508 */
509 lockdep_init();
510 set_task_stack_end_magic(&init_task);    //全局变量init_task,即手工创建的PCB,0号进程即最终的idle进程
511 smp_setup_processor_id();
512 debug_objects_early_init();
513
514 /*
515 * Set up the the initial canary ASAP:
516 */
517 boot_init_stack_canary();
518
519 cgroup_init_early();
520
521 local_irq_disable();
522 early_boot_irqs_disabled = true;

2、初始化一些中断向量 trap_init()

  • 中断向量表的初始化函数,设置了很多中断门(Interrupt Gate)
  • set_intr_gate:设置中断门

 
3、mm_init() 内存管理模块
void __init trap_init(void)
793{
794 int i;
795
796#ifdef CONFIG_EISA
797 void __iomem *p = early_ioremap(0x0FFFD9, 4);
798
799 if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
800 EISA_bus = 1;
801 early_iounmap(p, 4);
802#endif
803
804 set_intr_gate(X86_TRAP_DE, divide_error);
805 set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
806 /* int4 can be called from all */
807 set_system_intr_gate(X86_TRAP_OF, &overflow);
808 set_intr_gate(X86_TRAP_BR, bounds);
809 set_intr_gate(X86_TRAP_UD, invalid_op);
810 set_intr_gate(X86_TRAP_NM, device_not_available);
811#ifdef CONFIG_X86_32
812 set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
813#else
814 set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
815#endif
816 set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
817 set_intr_gate(X86_TRAP_TS, invalid_TSS);
818 set_intr_gate(X86_TRAP_NP, segment_not_present);
819 set_intr_gate(X86_TRAP_SS, stack_segment);
820 set_intr_gate(X86_TRAP_GP, general_protection);
821 set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
822 set_intr_gate(X86_TRAP_MF, coprocessor_error);
823 set_intr_gate(X86_TRAP_AC, alignment_check);
824#ifdef CONFIG_X86_MCE
825 set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
826#endif
827 set_intr_gate(X86_TRAP_XF, simd_coprocessor_error);
828
829 /* Reserve all the builtin and the syscall vector: */
830 for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
831 set_bit(i, used_vectors);
832
833#ifdef CONFIG_IA32_EMULATION
834 set_system_intr_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
835 set_bit(IA32_SYSCALL_VECTOR, used_vectors);
836#endif
837
838#ifdef CONFIG_X86_32
839 set_system_trap_gate(SYSCALL_VECTOR, &system_call);    //系统陷阱门,也是个系统调用
840 set_bit(SYSCALL_VECTOR, used_vectors);
841#endif
4、sched_init() 调度模块
5、其它模块初始化 rest_init()
  • init_process是一号进程。
393static noinline void __init_refok rest_init(void)
394{
395 int pid;
396
397 rcu_scheduler_starting();
398 /*
399 * We need to spawn init first so that it obtains pid 1, however
400 * the init task will end up wanting to create kthreads, which, if
401 * we schedule it before we create kthreadd, will OOPS.
402 */
403 kernel_thread(kernel_init, NULL, CLONE_FS);    //创建第一个用户态进程
404 numa_default_policy();
405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);    //内核进程来管理资源
406 rcu_read_lock();
407 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
408 rcu_read_unlock();
409 complete(&kthreadd_done);
三、总结
  总的来说在rest_init函数中,内核产生第一个真正的进程:
    (pid=1):init_idle(current, smp_processor_id())函数的调用把init_task初始化成idle task
  init_idle函数的第一个参数current就是&init_task,在init_idle中将会把init_task加入到cpu的运行队列中,这样当运行队列中没有别的就绪进程时,init_task(也就是idle task)将会被调用。
  sched_init()初始化函数内对0号进程,即idle进程进行初始化rest_init()->cpu_startup_entry()->cpu_idle_loop()就是一直循环,当系统没有进程需要执行的时候就调度idle进程,从内核启动开始一直存在,0号进程。0号进程创建了1号进程,并且还创建了内核中其他的一些服务线程。
  init目录下main.c中的start_kernel是启动内核的起点。

Linux内核分析作业第三周的更多相关文章

  1. 《Linux内核分析》第三周学习报告

    <Linux内核分析>第三周学习报告                                    ——构造一个简单的Linux系统MenuOS 姓名:王玮怡  学号:201351 ...

  2. 《Linux内核分析》第三周学习笔记

    <Linux内核分析>第三周学习笔记 构造一个简单的Linux系统MenuOS 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.stud ...

  3. 《Linux内核分析》第三周学习小结 构造一个简单的Linux系统OS

    郝智宇 无转载 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 第三周 构造一个简单的Linux系统Me ...

  4. 《Linux内核分析》 第三周 构造一个简单的Linux系统MenuOS

    Linux内核分析 第三周 构造一个简单的Linux系统MenuOS 张嘉琪 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/ ...

  5. 《Linux内核分析》第三周 构建一个简单的Linux系统MenuOS

    [刘蔚然 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] WEEK THREE ...

  6. 《Linux内核分析》第三周

    [李行之原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000] <Linux内 ...

  7. 《Linux内核分析》第三周:Linux系统启动过程

    杨舒雯 原创作品转载请注明出处 Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 一.实验--使用gdb跟踪调试内 ...

  8. 《Linux内核分析》第三周笔记 构造一个简单的Linux系统MenuOS

    构造一个简单的Linux系统MenuOS 一.linux内核源代码简介 三大法宝(存储程序计算机.函数调用堆栈.中断)和两把宝剑(中断上下文的切换:保存现场和恢复现场.进程上下文的切换) 1.在lin ...

  9. Linux内核分析(第三周)

    构造一个简单的linux系统menuOS. 一.简介 1.两把宝剑:中断-上下文的切换(保存现场和恢复现场) 进程-上下文的切换 2.linux-3.18.6 arch/x86目录下的代码是我们重点关 ...

随机推荐

  1. oc 的 协变性与逆变性

    ?协变性与逆变性是类型关系在范畴论的定义.是类型的继承关系在高阶类型中的定义? __kindof只是在统一继承体系下方便了类型转化,提供了使用时语法上的便捷:但是对于类型转换是否正确不做判定: kin ...

  2. Swift学习笔记十:属性

    1.存储属性       1. 作为特定类或结构实例的一部分,存储属性存储着常量或者变量的值. 存储属性可分为变量存储属性(keywordvar描写叙述)和常量存储属性(keywordlet描写叙述) ...

  3. Netty入门(十)解码分隔符和基于长度的协议

    我们需要区分不同帧的首尾,通常需要在结尾设定特定分隔符或者在首部添加长度字段,分别称为分隔符协议和基于长度的协议,本节讲解 Netty 如何解码这些协议. 一.分隔符协议 Netty 附带的解码器可以 ...

  4. JavaScript定时器的工作原理(翻译)

    JavaScript定时器的工作原理(翻译) 标签(空格分隔): JavaScript定时器 最近在看ajax原理的时候,看到了一篇国外的文章,讲解了JavaScript定时器的工作原理,帮助我很好的 ...

  5. 利用 share code 插件同步代码片段

    利用 Settings Sync可以同步 VS code 配置,但它只能同步插件,利用  Settings Sync 再配合 share code 插件可以同步自定义代码片段,可以把 VS code ...

  6. Block abstraction view(Create & Reference)

    在hierarchical design 中,一般需要调用 hard macro,top调用 macro 的方法有多种: 1. 调用macro对应的db 2. 调用 macro 的 ilm 模型(20 ...

  7. JS动态生成表格后 合并单元格

    JS动态生成表格后 合并单元格 最近做项目碰到表格中的单元格合并的问题,需求是这样的,首先发ajax请求 请求回来后的数据 动态生成表格数据,但是生成后如果编号或者(根据其他的内容)有相同时,要合并单 ...

  8. redis主从搭建

    两台服务器 127.0.0.101 A 主服务器 127.0.0.108 B 从服务器 从服务器设置 1.修改redis.conf 依次修改daemonize no改为daemonize yes  默 ...

  9. Android使用AsyncTask设置请求超时的注意事项

    备注:该篇文章为原创,转载请声明地址,谢谢! /** * AsyncTaskTools2集成了AsyncTask类 * 前三个参数为回到函数,最后一个为全局的Context */ final Asyn ...

  10. 腾讯笔试题 构造回文(LCS问题)

    给定一个字符串s,你可以从中删除一些字符,使得剩下的串是一个回文串.如何删除才能使得回文串最长呢? 输出需要删除的字符个数. 输入描述: 输入数据有多组,每组包含一个字符串s,且保证:1<=s. ...