设为首页 收藏本站
查看: 1743|回复: 0

[经验分享] 20179202杨晓桐

[复制链接]

尚未签到

发表于 2017-11-18 06:06:44 | 显示全部楼层 |阅读模式
一、跟踪分析内核的启动过程实验 :

1.启动Menuos:
  qemu仿真kernel:
  qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
DSC0000.png


知识补充:
  (1)bzImage 是 vmlinux 经过 gzip 压缩后的文件,是压缩的内核映像,“b”代表的是“big”(bzImage 适用于大内核,zImage 适用于小内核)。vmlinux 是编译出来的最原始的内核ELF文件;
  (2)根文件系统包括虚拟根文件系统和真实根文件系统。initrd 是“initial ramdisk”的简写,boot loader 将存储介质中的 initrd 文件加载到内存,内核启动时先访问 initrd 文件系统(虚拟的文件系统),然后再切换到真实的文件系统。

2.调试跟踪:
  

-S  开始处冻结CPU,方便调试  
-s  使用tcp端口1234来进行通讯,将进程信息传过去(在后面的调试中会用到)。若不想使用1234端口,可以使用-gdb tcp:xxxx来取代-s选项
  

DSC0001.png

  启动gdb,把内核加载进来,建立连接:
  file linux-3.18.6/vmlinux
  target remote:1234
  实践过程中出现以下错误:
DSC0002.png

  连接超时应该是没连接上冻结的系统,检查后发现进入gdb调试前讲QEMU窗口关闭了,打开后得以解决:
DSC0003.png

  在 start_kernel 处设置断点,继续执行,停在断点处:
DSC0004.png

  在 rest_init 处设置断点,继续执行,停在断点处:
DSC0005.png


3.内核启动分析(自己的大致理解):

(1)start_kernel()
  main.c 中没有 main 函数,start_kernel() 相当于是C中的main函数。start_kernel是一切的起点,在此函数被调用之前内核代码是用汇编语言写的,完成系统的初始化工作,为c代码的运行设置环境。由调试可得 start_kernel 在500行:
DSC0006.png


(2)init_task()
  start_kernel() 函数几乎涉及到了内核的所有模块,如:trap_init()(中断向量的初始化)、mm_init()(内存管理的初始化)sched_init()(调度模块的初始化)等,首先是510行的init_task():
  struct task_struct init_task = INIT_TASK(init_task);
  可以看出 init_task(0号进程)是 task_struct 类型,是进程描述符,使用宏INIT_TASK对其进行初始化。接下来就是对各种模块的初始化:
DSC0007.jpg

              图片来源于分析Linux内核的启动过程

(3)rest_init()
  通过rest_init()新建kernel_init、kthreadd内核线程:
DSC0008.png

  403行代码 kernel_thread(kernel_init, NULL, CLONE_FS);,由注释得调用 kernel_thread()创建1号内核线程(在 kernel_init 函数正式启动):

注:对比 init_task 和 kernel_thread()
DSC0009.png

  kernel_thread()是 fork 出了一个新进程来执行kernel_init 函数,而 init_task 是使用宏进行初始化的。也就是说0进程不是系统通过 kernel_thread 的方式(也就是 fork)创建的(init_task 是唯一一个没有通过 fork()产生的进程)。
  405行代码 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);1 调用 kernel_thread()执行 kthreadd函数,创建 PID=2的内核线程:
DSC00010.png

  此函数的任务是管理和调度其他内核线程 kernel_thread。for 循环中运行 kthread_create_list 全局链表中维护的 kthread, 在create_kthread()函数中,会调用 kernel_thread 来生成一个新的进程并被加入到此链表中,因此所有的内核线程都是直接或者间接的以 kthreadd 为父进程。

4.总结:
  (1)init_task()(PID=0)在创建了init进程后,调用 cpu_idle() 演变成了idle进程,执行一次调度后,init进程运行;
  (2)1号内核线程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execve执行 init 函数,演变成 init 进程(用户态1号进程),init 进程是内核启动的第一个用户级进程;
  (3)kthreadd(PID=2)进程由0号进程创建,始终运行在内核空间, 负责所有内核线程的调度和管理 。
DSC00011.png

  注:Linux下的进程类别(内核线程、轻量级进程和用户进程)以及其创建方式
  参考:
  Linux下0号进程的前世(init_task进程)今生(idle进程)
  Linux下1号进程的前世(kernel_init)今生(init进程)
  Linux下2号进程的kthreadd

二、课本笔记:

1.进程调度:
    进程调度程序是在可运行态进程之间分配有限的处理器时间资源的内核子系统。Linux提供了抢占式的多任务模式,在此模式下,由调度程序决定一个进程的运行,以便其他进程能得到执行机会(抢占:抢占的挂起动作)。进程在被抢占前能运行的时间叫做进程的时间片,即分配给每个可运行进程的处理器时间段。
    Linux内核将进程分成普通进程和实时进程。普通进程用nice值表示时间片的比例(CFS调度器将处理器的时间比划分给了进程,越大的nice值将被赋予低权重,丧失一小部分的处理器时间使用比);实时进程采用实时优先级,数值越高优先级越高(两种实时调度策略为SCHED_FIFO和SCHED_RR,SCHED_RR是带有时间片的SCHED_FIFO)。任何实时进程的优先级都高于普通进程。
    CFS虽没有时间片的概念,但必须维护每个进程运行的时间记账,它会挑一个具有最小vruntime(存放进程的虚拟运行时间)的进程(利用红黑树迅速找到最小vruntime值的进程)进行调度。休眠(被阻塞)进程把自己标记成休眠状态,从可执行红黑树中移出,放入等待队列,然后调用schedule()选择和执行其他进程,唤醒时被置成可执行状态,然后再从等待队列中移到可执行红黑树中。
    当内核即将返回用户空间时,内核会检查need_resched是否设置,如果设置,则调用schedule(),发生用户抢占。 内核抢占是指在内核态运行的进程在执行期间可能被另一个进程取代(没有读懂课本对内核抢占的解释,参照Linux用户抢占和内核抢占详解(概念, 实现和触发时机),如果内核处于相对耗时的操作中, 比如文件系统或者内存管理相关的任务, 其他进程无法执行, 无法调度, 这就造成了系统的延迟增加, 用户体验到”缓慢”的响应。比如如果多媒体应用长时间无法得到CPU, 则可能发生视频和音频漏失现象.启用内核抢占可解决此问题)

2.内核数据结构:
  (1)Linux内核链表不同于传统链表,它不是将数据结构塞入链表,而是将链表结点塞入数据结构:
DSC00012.png

  (2)Linux内核通用队列实现成为kfifo,提供enqueue和dequeue,kfifo对象维护入口偏移和出口偏移两个偏移量;
  (3)Linux映射一个唯一的标识数(UID)到一个指针(有点像字典类型,每个唯一的id对应一个自定义的数据结构);
  (4)红黑树和平衡二叉树的区别在于它使用颜色来标识结点的高度,它所追求的是局部平衡而不是平衡二叉树中的非常严格的平衡。(课本上对红黑树的描述我也没有看明白,查阅资料数据结构之红黑树,了解了红黑树的性质(根是黑色;所有叶子都是黑色(叶子是NIL节点);如果一个节点是红的,则它的两个儿子都是黑的;从任一节点到其叶子的所有简单路径都包含相同数目的黑色节点)及红黑树的插入删除。虽然红黑树追求的是局部平衡,但我感觉和平衡二叉树的插入删除还是难了点,也有可能是刚接触的原因QAQ)

三、小结:
    本周学习中遇到了很多不明白的指令和术语,一边实践一边查阅资料,在阅读资料中又会由此引出新的问题(如在搜索init进程中看到先是内核线程又是用户进程,然后如果不理解二者区别,就没法弄明白1号进程的前世今生,只能继续搜索内核线程和用户进程的区别)过程辛苦,但好在问题大部分得以解决,还有小部分需要再强化理解。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-408084-1-1.html 上篇帖子: (转)Linux-HA实战(1)— Heartbeat安装 下篇帖子: 【转载】排查Linux机器是否已经被入侵
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表