linux查看硬盘smart_linux启动过程分析

在描述linux系统启动过程之前,我们需要先来看看linux在启动之后,物理内存的布局情况,我们可以通过查看文件/proc/iomen获得详细的物理内存布局图,在我的系统中,/proc/iomen文件内容如下:

52dacd8172b8181a798573157250909b.png

linux物理内存布局

很多人在用cat或者vi查看这个文件的时候,发现前面的地址值都是清一色的0,不知道为什么?是时候展现真正的技术了,只需要在cat或者vi前面加上sudo就好了,没有点特殊权限是不会让你看的。另外,上面这张图是在32位系统上的布局图。如果你想深入研究linux的内核原理,建议在32位系统上,这样在查看内存布局方面比较方便。如果只是“使用”linux,可以直接用64位的。

在0.12版本内核中,由于内核小于640kb,所以被加载到0-640k空间内。而我们在上图中看到,内核是从1M开始的内存区域开始加载的。这是因为,在后来版本的linux内核大小超过了640kb,如果加载到从4kb开始的640kb空间里,就会占用后面显示缓冲区和各种ROM区域,该部分区域是由系统保留的,用于映射系统BIOS和显卡ROM。而内核必须被装载到一个连续的内存区中,所以只能从1M开始的位置进行加载。这里注意BIOS ROM和显卡ROM是和内存RAM统一编址的。

首先,在我们启动电源的那一刻,cpu首先跳转到内存0xFFFFFF0处读取指令并执行,该地址位置正是BIOS ROM的映射区,存放的是BIOS的代码。系统执行BIOS用于各个硬件子系统的自检和初始化。

执行完BIOS后,我们的硬盘等设备都已经处于可用状态了,系统就会去读取第一个可启动设备(通常就是硬盘)的第一个扇区,也就是我们经常说的MBR,这里存放的就是用于加载内核的bootloader,现在基本都是grub了。grub会将我们的linux内核加载到内存中,那么grub是从哪里加载linux内核的呢?当然是从硬盘加载到内存了。我们的linux内核映像文件就放在硬盘/boot分区里。在我的系统中,/boot目录如下:

97143b3781749a4a8d03d5cb3351c673.png

boot目录

其中vmlinuz-4.15.0-20-generic这个文件就是grub将会加载到内存中的linux内核映像文件了,这里采用的是压缩的形式存放的,所以加载到内存中还需要解压缩。而grub目录中存放的是grub的配置文件,grub被加载到内存中,首先会读取该目录中的配置文件,所以如果你想对grub进行配置,就可以在这个目录里修改配置文件。注意,该目录中存放的是配置文件,并不是grub的可执行代码文件,grub的可执行代码我们刚才已经说了,是存放在硬盘的第一个扇区中,这个是在安装系统的时候写入该扇区的。

在该目录中,值得关注的还有一个initrd.img-4.15.0-20-generic文件,这个文件是用来做什么的呢?我们知道,内核在启动的过程中,要先挂载根目录,挂载根目录肯定要能识别硬盘,而识别硬盘需要硬盘设备驱动程序,而我们的linux为了减少自己的体积,并不会将设备驱动程序编译到自己的内核映像中,而是将大部分设备驱动程序编译成单独的模块,动态的加载设备驱动程序。模块文件一般都放置在/lib/moduls/目录下。这时候就出现了一个问题了,linux要挂载硬盘,首先需要能识别硬盘,需要硬盘设备驱动程序,而设备驱动程序又在硬盘的/lib/moduls/目录下,而此时硬盘还没有挂载,就无法取得该目录,无法取得该目录就没法加载设备驱动程序,没有设备驱动程序,就无法加载硬盘,好像陷入了无法解决的死循环。Linux内核的开发者们,当然不允许这种互相踢皮球的现象存在,于是想出了一个办法,那就是虚拟文件系统RAM disk,也就是我们看到的这个文件initrd.img-4.15.0-20-generic,该文件也会在系统启动的过程中由boot loader(grub)加载,加载到内存中解压缩后,会临时充当linux的根文件系统,该文件系统中存放了linux所需设备的驱动程序。我们可以查看该文件的内容,就是一个比较完整的跟文件系统。具体的查看方式,这里就不详细阐述了。

/boot目录下还有几个文件,config是内核在编译阶段的一些配置选项,system.map为系统的符号在虚拟地址空间的地址。

到这里我们的内核就加载到内存中了,并开始执行,内核会在执行一系列的初始化操作后,变成0号idle进程,0号进程会启动一个叫kthreadd的内核守护线程,由该线程启动一系列的内核线程,最后0号进程会启动我们的第一个用户层进程init,目前大部分发行版的init进程执行的是systemd了。我们用ps -ef可以查看系统中启动的进程,在我的系统中执行ps -ef命令如下:

464639478fa538428fa110b113afb6fe.png

ps -ef

其中COMMAND列中带中括号的就是系统的内核线程,剩下的就是系统启动的用户层进程。其实他们本质上都是一样的,都是linux进程,只是一个是在内核空间执行,另一个是在用户空间执行的。通过pid和ppid我们也能看出,所有内核守护线程都是由kthreadd启动的,而kthreadd的父进程id号是0。而我们看到pid号为1的进程就是我们的init进程,他同样也是由0号进程启动的。通过COMMAND列我们看到init进程启动的是/sbin/init这个可执行文件,通过ls -al发现,该文件正是systemd的链接,所以我们的init进程其实就是systemd了。

systemd正是用户空间所有进程的父进程了,所有的用户空进进程都是由他来启动的,我们也可以通过pstree命令直观的看到系统中进程的父子关系:

30b5e1579cfb4d1c2584bf04dcde13b9.png

pstree

我们通过pstree发现系统中所有的进程都是由systemd启动的,由于我是通过ssh远程登录的linux,所以也可以看到bash是由sshd启动的,这个也就是我在前几篇文章重点讨论的shell了。

再往下就是systemd的启动过程了,我不打算在这篇文章中详细讨论了,我会在下一篇尝试探讨systemd的启动过程。为什么说用尝试探讨,因为我发现,很多东西,懂了跟写出来是完全不一样的,就像这篇文章,一开始我以为写个启动过程会很容易,但是写着写着就会发现,内容实在是太庞大了,很多东西即使弄懂了,但是把它写出来好像也没有那么容易,所以只能说尝试了。

结合上一篇文章《linux shell环境配置文件》,到这里,基本上把linux启动过程的方面方面都涉及到了,但是不可能在一篇文章中讨论所有的细节。比如linux内核的启动过程,只是几句话带过了。本文权当是给各位抛砖引玉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值