博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
第三节 构造一个简单的Linux系统MenuOS——20135203齐岳
阅读量:5846 次
发布时间:2019-06-18

本文共 2384 字,大约阅读时间需要 7 分钟。

第三节 构造一个简单的Linux系统MenuOS

By 20135203齐岳

Linux内核源代码

  • arch/ 支持不同cpu的源代码
  • Documentations/ 文档存储
  • init/ 内核启动相关代码
  • kenerl/ 进程调度相关代码
  • ipc/ 进程间通信
  • lib/ 公共库文件
  • mm/ 内存管理相关的代码

构造一个简单的Linux系统MenuOS

使用自己的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.git  # 如果被墙,可以使用附件menu.zip cd menugcc -o init linktable.c menu.c test.c -m32 -static –lpthread #将内核编译成一个名为init的可执行文件,系统默认第一个用户进程为init,称为1号进程cd ../rootfs cp ../menu/init ./#将init文件拷贝到rootfs目录下find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

启动MenuOS系统

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

第二句代码需要重点分析:

  • qemu:启动已经安装在系统中的相当于虚拟机的程序qemu,这个程序为内核的启动提供一个上下文环境
  • -kernel 文件名+路径:启动内核,内核经过编译之后形成一个名为init的文件,之前我们已经将它拷贝到rootfs文件目录之下,并通过cpio的方式将rootfs下的文件打包成一个名为rootfs.img的镜像文件。
  • -initrd rootfs.img:指定rootfs为为启动时的硬件驱动

经过以上代码之后,rootfs.img会找到init这个可执行文件,init又是由MenuOS这个内核源代码编译而来,由此完成使用自己的Linux系统环境搭建并启动一个内核——MenuOS的过程。

744942-20160311173100397-1505730314.jpg

跟踪调试Linux内核的启动过程

使用gdb跟踪调试Linux内核的方法

使用gdb跟踪调试内核

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

744942-20160311173125475-296930416.jpg

关于-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之前,也可以在之后

关于符号表

内核编译的时候为什么要生成符号表?

所谓内核符号表就是在内核内部函数或变量中可供外部引用的函数和变量的符号表,如下图所示。

744942-20160311173156913-314713817.jpg

在内核符号表中,左边一列是符号地址,右边一列是函数和变量。在汇编语言当中函数的调用通过Jump等机器指令来完成,于是就需要函数名,变量名和内存地址的映射,这种映射关系保存在符号表中,在调试的时候也会根据这种映射关系设置断点。

如果不加载符号表或者符号表加载错误,就会出现以下报错:

744942-20160311173212835-472492917.jpg

符号表加载成功之后断点设置成功,可以跟踪分析调试:

744942-20160311173301819-1069076443.jpg

简单分析start_kernel

  • trap_init() 初始化一些中断向量,管理硬件中断

744942-20160311173327679-253518890.jpg

这里的SYSCALL_VECTOR是一个系统调用,用指令的方式来触发中断。

  • mm_init() 内存管理模块

  • sched_init() 调度模块

  • rest_init()

rest_init()中的kernel_init其中945行处有一个run_init_process

744942-20160311173346335-677964701.jpg

这也就是Linux系统中的1号进程,是第一个用户态进程,默认是根目录下的一个程序;如果根目录下没有这个进程,系统会寻找其他的默认进程作为1号进程,当系统没有进程需要执行时就调度到idle进程。

rest init()就是一个0号进程,在start_kernel内核一启动时就一直存在;然后这个0号进程就创建了1号进程kernel_init,接下来还创建了其他的一些服务类的内核线程如kthreadd。这样整个系统就启动起来了。​

参考资料

【原创作品转载请注明出处】 1.《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000

2.《 linux内核符号表 》

转载于:https://www.cnblogs.com/July0207/p/5266594.html

你可能感兴趣的文章
Linux ACE 网络模块
查看>>
正则表达式(基本)
查看>>
如何修改php.ini参数
查看>>
腾讯云 安装web环境
查看>>
常用网站收集
查看>>
SQL自增列重置
查看>>
eclipse在线安装maven plugin
查看>>
惠普瘦客户机t610高性能桌面云终端
查看>>
打造属于自己的博客 - Asp.net三层架构
查看>>
ASP.NET对象的使用
查看>>
我的友情链接
查看>>
数据库文章收集
查看>>
syslog增强版rsyslog介绍
查看>>
MySQL 备份和还原
查看>>
radware基于端口的负载
查看>>
(九)正则表达式、sed、awk(二)
查看>>
Wrapping libvirt Virtual Networks Around Open vSwitch Fake Bridges
查看>>
分布式利器Zookeeper(二):分布式锁
查看>>
python之yield使用
查看>>
Python中的反射
查看>>