linux 内核代码学习(十)--Linux内核启动和文件系统

news2024/11/17 17:28:40

前面第九章介绍了linux内核+文件系统从软盘启动的几种方式:1、从软盘直接启动的linux,软盘上包括内核及简单文件系统;2、从软盘直接启动的linux,将内核与文件系统分别放置在一张软盘上;3、Grub做为引导程序,软盘上包括内核及简单文件系统;4、用sysLinux引导,软盘上包括内核及简单文件系统。本章介绍的linux内核+文件系统从软盘启动的方式的特点是:Grub做为引导程序,分为两张软盘启动,第一张软盘包括grub、内核、简单文件系统、以及一个自己编写的readkey程序;第二张软盘包括一个完整的文件系统;系统启动过程中通过readkey程序提示插入第二张软盘,并通过第一张软盘中的简单文件系统将第二张软盘中的文件系统解压,切换到第二张软盘的完整文件系统,释放第一张软盘的简单文件系统;这种方式可以完成更复杂的启动,可以自己DIY自己的linux,进一步可以制作自己的linux发行版。

为了方便理解这个例子,先介绍目录结构如下:
/home/mygrub
  ├─bootldr/
  │ ├─grub/
  │ ├─kernel/
  │ │ ├─images/
  │ │ └─linux-2.4.20/
  │ └─initrd/ 
       │   ├─mkinitrd.sh
  │   ├─local/
  │   └─ramdisk/
  ├─rootfs/
  │ ├─mkrootfs.sh
  │ ├─ramdisk/
  │ └─local/
  └─lib/
使用Grub做为引导程序,并使用initrd(初始RAM磁盘)来辅助Linux的启动。两张软盘分别命名为bootldr盘和rootfs盘,在bootldr盘中内容为grub、内核、initrd;rootfs盘中是压缩过的根文件系统。系统启动时bootldr盘的Grub定位并执行内核,然后内核解开initrd,并执行linuxrc文件(这需要在grub.conf配置文件中设置初始化参数init=/linuxrc rw),这个文件负责提示用户更换rootfs盘并将其中内容解压至内存中,然后执行刚刚解压的init(注意此时的init在第二张盘文件系统中)继续启动过程。

一、第一张bootldr盘的制作
插入一张软盘,然后将其格式化,然后加载到/mnt/floppy
mke2fs -m 0 /dev/fd0
mount -t ext2 /dev/fd0 /mnt/floppy -o loop
在其中创建/boot/grub目录
mkdir -p /mnt/floppy/boot/grub
将系统中/boot/grub下的device.map, stage1, stage2 复制到/mnt/floppy/boot/grub中,
cp /boot/grub/stage1 /mnt/floppy/boot/grub
cp /boot/grub/stage2 /mnt/floppy/boot/grub
grub
在 grub> 提示符处,输入:
grub> root (fd0)
grub> setup (fd0)
grub> quit
cp /boot/grub/grub.conf /mnt/floppy/boot/grub

编辑grub.conf, 内容如下:
timeout 10
default 0
title XB_Linux (2.4.20-8)
  root (fd0)
  kernel /boot/bzImage ro root=/dev/ram0 init=/linuxrc rw ##必须指定启动参数init=/linuxrc rw,否则会报错提示说init程序多次调用,导致文件系统初始化不完善。见内核文档initrd.txt详细说明
  initrd /initrd.gz
然后制作grub.conf的link文件menu.lst
ln -s /mnt/floppy/boot/grub/grub.conf /mnt/floppy/boot/grub/menu.lst
这样grub就被安装到bootldr盘上了。

没有配置启动参数的时候,会有init多次调用的提示,导致第二张盘中的文件系统中的/etc/目录下的初始化文件不能执行,比如fstab、inittab。 

二、定制Linux内核:由于软盘大小的限制,内核应尽可能只包含必要的一些支持,对于本文中的例子一定要选上initrd支持。比如如果做为系统修复盘的话,必要的支持包括:IDE,PCI,和需要的文件系统类型等等就可以了,而没有必要网络支持,当然,如果做为路由器或者防火墙的话,网络支持是必要的,而其他的可相应的删除掉。
  #make [xconfig | menuconfig | config]
  #make bzImage
  如果添加了模块的支持,还需要
  #make modules
  之后就得到了内核镜像bzImage。如果bzImage的大小超出了软盘的限制,就需要重新再来配置一下。将编译好的bzImage放到bootldr盘的根目录下,如果把bzImage改了名字,要注意与grub.conf中的名字一致。
cp /mnt/hgfs/linux-2.4.20/arch/i386/boot/bzImage /mnt/floppy/boot/
umount /mnt/floppy/

三、制定initrd
  在initrd/local目录下建立bin, dev, etc, lib, proc, sysroot, usr目录。其中dev目录下包括必要的设备文件,
比如tty, ram, console,fd0等等,
mknod dev/tty c 5 0
mknod dev/ram0 b 1 0
mknod dev/console c 5 1
mknod dev/null c 1 3
 bin中必要的可执行文件有gzip,chroot, cp, cpio, dd, echo, mount, pivot_root,readkey, sh, test等。Busybox提供了其中大部分。 gzip, dd, cpio用来解压缩第二张软盘上的内容,chroot,pivot_root用来转换根目录。
cp /home/xb/busybox-1.00/_install/bin/busybox  bin/
ln -s busybox gzip
ln -s busybox chroot
ln -s busybox cp
ln -s busybox cpio
ln -s busybox dd
ln -s busybox echo
ln -s busybox mount
ln -s busybox pivot_root
ln -s busybox sh
ln -s busybox ls
因为我的busybox编译的时候用的是默认的sysinit script:
#define INIT_SCRIPT  "/etc/init.d/rcS"    /* Default sysinit script. */
而我们的initrd软盘中并没有/etc/init.d/目录及rcS脚本文件,因此我们在grub配置文件中配置了启动参数init=/linuxrc rw,这样内核就会直接执行简单文件系统根目录下的linuxrc文件。

[root@localhost initrd]# cat local/linuxrc
#!/bin/sh

#把sysroot目录mount到一块内存上,并建立tmpfs文件系统。
echo "Mounting new root filsystem ..."
mount tmpfs /sysroot -t tmpfs
cd /sysroot

#下面的readkey是一个很简单的程序,当启动过程执行到这里的时候暂停,等待换入第二章软盘,然后#接受任意键输入继续执行启动过程,要注意的是最好使用静态链接。
echo " "
echo -en "Insert the second disk and press ANY key..."
readkey > /dev/null
echo " "

#将第二章软盘上的内容解压到sysroot目录(内存)中。
echo "Loading root-archive from floppy ..."
dd if=/dev/fd0 bs=1k | gzip -d | cpio -idv
#下面将initrd中的文件copy到sysroot/bin目录下,这样可以把根文件系统中一部分内容放到initrd(第##一张软盘)中,因为软盘容量有限,当第一张软盘空间有剩余,而第二章软盘空间紧张的时候这会非常##有用。
echo "Copying:"
for file in gzip chroot cp cpio echo readkey; do
echo -en " "; echo -n $file
cp /bin/$file ./bin/$file
done
#下面将/目录设定为当前目录,即sysroot,并执行刚刚从rootfs盘中解压出来的init。
echo " "
echo "Pivoting / ..."
pivot_root . mnt/initrd
echo "Starting init process..."
exec chroot . /sbin/init <dev/console >/dev/console 2>&1
echo -en"Something went wrong ..."
/bin/sh || /mnt/initrd/bin/sh
[root@localhost initrd]#

当initrd所有必须的文件都放到bootldr/initrd/local目录下之后,进入到bootldr/initrd目录,就可以执行bootldr/initrd/mkinitrd.sh来创建initrd镜像文件。mkinitrd.sh的内容为:
#!/bin/sh
  mount -t ext2 /dev/fd0 /mnt/floppy
  rm -f /mnt/floppy/initrd.gz
  rm -f initrd.gz
  取4M大小的内存块格式化为ext2格式,并将其mount到bootldr/initrd/ramdisk上。
  dd if=/dev/zero of=/dev/ram9 bs=1k count=4096
  mke2fs -m 0 /dev/ram9
  mount -t ext2 /dev/ram9 ramdisk/
  把local中的文件复制到ramdisk目录中,也就是那块内存中。
  cp -R local/* ramdisk/
  umount ramdisk
  将内存中的内容压缩为initrd.gz,并复制到bootldr盘中
  dd if=/dev/ram9 bs=1k | gzip -v9 > initrd.gz
  cp initrd.gz /mnt/floppy/
  umount /mnt/floppy
  这样,bootldr盘就完成了。

 [root@localhost xb]# cat readkey.c
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>

#if 0
// 定义按键值
#define KEY_ESC 0x1b  
// 定义readkey函数
int readkey(void) {
    struct termios oldattr, newattr;
    int ch;  
    // 获取当前终端设置
    tcgetattr(0, &oldattr);
    newattr = oldattr;
    // 设置非回显模式
    newattr.c_lflag &= ~(ECHO | ICANON);
    tcsetattr(0, TCSANOW, &newattr);  
    // 读取键盘输入
    ch = getchar();  
    // 恢复原来的终端设置
    tcsetattr(0, TCSANOW, &oldattr);  
    return ch;
}  
int main() {
    int key;  
    printf("Press a key, and then press Enter: ");
    fflush(stdout); // 清空输出缓冲区  
    key = readkey();  
    if (key == KEY_ESC) {
        printf("You pressed the ESC key.\n");
    } else {
        printf("You pressed the '%c' key.\n", key);
    }  
    return 0;
}
#endif
 
int main()
{
    struct termios oldattr, newattr;
    int ch;  
    // 获取当前终端设置
    tcgetattr(0, &oldattr);
    newattr = oldattr;
    // 设置非回显模式
    newattr.c_lflag &= ~(ECHO | ICANON);
    tcsetattr(0, TCSANOW, &newattr);  
    // 读取键盘输入
    ch = getchar();  
    // 恢复原来的终端设置
    tcsetattr(0, TCSANOW, &oldattr);  
    return ch;
}
四、定制根文件系统
  一个根文件系统需要包含支持Linux系统运行的所有文件。通常包括:
  基本的文件系统结构
  基本的目录: /dev, /proc, /bin, /sbin, /etc, /usr, /tmp,/mnt,/mnt/initrd等。
  基本的工具: sh, ls, cp, cd, mv等。
  基本的配置文件: rc, inittab, fstab等。
  设备: /dev/hd*, /dev/tty*, /dev/fd0, /dev/ram*, /dev/console等.
  基本的运行库。
  Busybox和Tinylogin是在嵌入式系统上常用的工具包,它们包含了上面提到的常用的工具和目录结构等,而且经过重新改写后所生成的代码比普通的Linux系统上的工具要小的多。编辑Busybox的Config.h文件,选择自己需要的工具。修改Busybox和Tinylogin的Makefile文件,制定它们使用静态链接方式(DOSTATIC=true),这样就不需要在生成的系统中添加运行库了。将编译好的Busybox和Tinylogin文件放到rootfs/local中。

对于tinylogin,操作和busybox完全相同。也要静态编译,然后把login,passwd,adduser等帐户管理的工具建立和tinylogin的链接即可。需要注意的是有些工具是在sbin当中的,所以也可以把tinylogin拷到 sbin目录下,bin下的工具要想链接到tinylogin,可以如下操作:

ln –s tinylogin ../bin/login

有些bin和sbin下的工具是busybox和tinylogin中所没有的,必须从完整的系统中拷过来,例如在这个系统中,由于选择vi时编译出错,所以vi是直接从主盘上拷过来的,而且必须把这个工具使用的相应的库也拷到lib下面。如使用ldd vi,就可以看到vi使用了哪些库,然后把这些库拷到/mnt/lib下就可以了。Tinylogin目前已经整合到busybox中了。

https://tinylogin.busybox.net/

     

在rootfs/local中在自己创建下面几个目录:dev/, tmp/, etc/, proc/可以将系统中/dev下的设备复制到这个目录下,只需要复制必要的就可以了,例如:
  #cp -dpR /dev/tty[0-9]    rootfs/local/dev
  #cp -dpR /dev/ram*       rootfs/local/dev
  但是要注意一定要包含必要的接各设备/dev/console, /dev/kmem, /dev/mem, /dev/tty, /dev/ram0,/dev/null等。etc/目录下包含了目标系统运行所必须的配置文件,它包括的内容依赖于目标系统所要运行的程序。最低限度,它包括下面几个文件:inittab、rc、fstab、passwd、group、shadow、termcap等。做为init进程的参数,inittab可以非常简单,仅需要包括下面几行即可:
[root@localhost local]# cat etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:/bin/sh
#::askfirst:/bin/login
#tty2::askfirst:/bin/login
#tty3::askfirst:/bin/login
#tty4::askfirst:/bin/login
#::ctrlaltdel:/sbin/reboot
#::restart:/sbin/init
#::shutdown:/bin/umount -a -r
#::shutdown:/sbin/swapoff -a

将::askfirst:/bin/login替换为::askfirst:/bin/sh,否则会出现如下面的问题,不能进入到linux环境中:

其中sysinit指明系统初始化脚本rc。rc所包含内容也可以非常少:
  #!/bin/sh
  /bin/mount -av
  /bin/umount /mnt/initrd
  /bin/hostname papaya
fstab的内容为:
  none/procprocdefaults0 0
  none/tmptmpfsdefaults0 0
  其他的配置文件可以从原来的系统中获得,然后修剪掉不必要的内容即可。现在在/rootfs中已经包含了运行一个最低限度Linux系统所必须的所有文件和工具,下面需要将它们压缩成一个文件系统了。插入rootfs软盘并执行rootfs/mkrootfs.sh
  #!/bin/sh
  rm -f rootfs.cpio.bz2
  dd if=/dev/zero of=/dev/ram0 bs=1k count=4096
  mke2fs /dev/ram0
  mount -t ext2 /dev/ram0 ramdisk/
  cp -R local/* ramdisk/
  cd ramdisk/
  find . -depth -print | cpio -o > ../rootfs.cpio
  cd ..
  gzip -v9 rootfs.cpio
  umount ramdisk
  dd if=rootfs.cpio.gz of=/dev/fd0 bs=1k
  OK,rootfs盘也完成了

 五、在vmware虚拟机中的测试效果

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176734.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【软件类】OPPO 2024届校招正式批笔试题-研发通用(C卷)

昨天做了一场OPPO的&#xff0c;BC两题都速切了&#xff0c;其中B为语法题&#xff0c;C为思维题&#xff0c;想明白mid的范围即可&#xff0c;但A题真给我搞汗流浃背了&#xff0c;倒不是A题难&#xff0c;而是数据卡的很死。从下午一直调到了晚上还是TLE了&#xff0c;最后出…

测试矩阵:快速完成测试用例设计的高效模板

一般来说&#xff0c;测试矩阵用于整理测试思路&#xff0c;便于其他人进行测试审核&#xff0c;后续测试用例基本基于测试矩阵内容进行&#xff0c;测试矩阵主要元素为测试模块、测试场景和测试点&#xff0c;其他内容可在设计测试用例时再进行完善&#xff0c;以下模板包含了…

上海我店:创新模式引领本地生活新风尚

近年来&#xff0c;一个名为“上海我店”的新兴平台在网络空间中迅速崛起&#xff0c;其公布的业绩令人瞩目——在短短三年内&#xff0c;交易流水已跨越百亿大关&#xff0c;并在最近一个月内迎来了近百万的新增注册用户。这一强劲的增长势头&#xff0c;无疑吸引了众多商家和…

服务器数据恢复—raid磁盘故障导致数据库文件损坏的数据恢复案例

服务器存储数据恢复环境&故障&#xff1a; 存储中有一组由3块SAS硬盘组建的raid。上层win server操作系统层面划分了3个分区&#xff0c;数据库存放在D分区&#xff0c;备份存放在E分区。 RAID中一块硬盘的指示灯亮红色&#xff0c;D分区无法识别&#xff1b;E分区可识别&a…

STM32F407HAL库输出互补PWM波以及死区时间计算

互补PWM波配置 STM32F407VET6的高级定时器TIM1、TIM8可以生成互补的PWM波&#xff0c;用HAL库配置非常方便。 我们使用高级定时器TIM1&#xff0c;选择一个通道&#xff08;我这里选择通道二&#xff09;&#xff0c;然后选择PWM Generation CH2 CH2N。这里N的意思是互补&…

基于趋近律的滑模控制器设计、仿真(S-function)

目录 一、什么是滑模控制?1. 滑模面2. 控制策略3. 抗干扰和鲁棒性4. 滑模控制的应用 二、什么是趋近律&#xff1f;1. 趋近律三大设计目标2. 常见的趋近律形式1. 等速趋近律2. 指数趋近律3. 幂次趋近律 三、滑模控制器设计四、滑模仿真示例1. Simulink仿真框图2. 不同k值下的仿…

JAVA全球美业新风尚国际版同城美容美发到店上门一体化服务系统小程序源码

全球美业新风尚&#xff0c;美丽触手可及&#xff01;✨ &#x1f30d; 开篇&#xff1a;引领国际美业新潮流 在这个追求个性与美丽的时代&#xff0c;美容美发已不再是简单的日常护理&#xff0c;它成为了我们展现自我、追求品质生活的一种方式。而“全球美业新风尚国际版同…

ASP.NET Zero是什么?适合哪些业务场景?

一、ASP.NET Zero是什么&#xff1f; ASP.NET Zero 是一个基于 ASP.NET Boilerplate (ABP) 框架的模板项目&#xff0c;它提供了预建的页面和强大的基础设施架构&#xff0c;以便开发者能够快速开发应用层。它的特点包括但不限于&#xff1a; 多合一解决方案&#xff1a;提供多…

4.数据结构与算法-线性表的顺序表示和实现

2.1 线性表的定义和特点 线性表例子 线性表的逻辑特征 2.2 案例引入 案例2.1 案例2.1&#xff1a;一元多项式的运算 案例2.2&#xff1a;系数多项式的运算 用时间换取空间--线性数组相对链式访问速度快 但这种方法链式更节省空间&#xff0c;所以用时间换取空间 案例2.3&…

2024平价电容笔推荐!精选五大靠谱电容笔测评盘点!

现在电子设备已经成为我们生活、学习和工作中不可或缺的重要工具。而电容笔作为与电子设备紧密配合的配件&#xff0c;其重要性也日益凸显&#xff0c;为我们的数字操作体验带来极大的便利和提升。然而&#xff0c;市场上电容笔的品牌众多&#xff0c;价格、性能和品质参差不齐…

工业制氮机在食品行业的应用优势

作为一种高效、环保的设备&#xff0c;制氮机通过物理方法从空气中分离出高纯度氮气&#xff0c;为食品行业提供了全方位的品质提升和安全保障。本文将详细探讨工业制氮机在食品行业的应用优势。 一、保障食品质量与安全性 工业制氮机在食品行业中最为显著的应用优势之一&#…

Ubuntu-WSL2一键设置代理操作

现状&#xff1a; Window11中拥有自己的代理软件 &#xff0c;可以科学上网已在WSL2中安装Ubuntu22.04 需求&#xff1a; Ubuntu-WSL2实现科学上网 实现&#xff1a; 参考&#xff1a;为 WSL2 一键设置代理 Linux 子系统中的网关指向的是 Windows&#xff0c;DNS 服务器指…

深入调研400+手游公司,此时正是入行好时机?

自2022年起&#xff0c;手游市场在疫情阴霾消散后遭遇的增长瓶颈&#xff0c;成为了业界持续聚焦的热点议题。转眼间&#xff0c;两年时光匆匆流逝&#xff0c;这一领域的现状与前景究竟几何&#xff1f; 国际知名发行商Sandsoft最新出炉的《发行商洞察报告》中&#xff0c;对…

开源物联网技术--TFT_LCD屏驱动软硬件设计分享

01 一、物联网系统中为什么要使用TFT-LCD屏 在物联网系统中使用TFT-LCD&#xff08;薄膜晶体管液晶显示器&#xff09;驱动芯片的原因主要可以归纳为以下几点&#xff1a; 专业性与高效性 专业图形处理&#xff1a;TFT-LCD驱动芯片内置了专业的图形处理引擎&#xff0c;能够…

探索Langchain与国内智谱清言:构建先进的智能对话系统[第二课]

在当今的人工智能领域&#xff0c;构建一个能够流畅对话的智能系统是许多企业和开发者的目标。Langchain和国内智谱清言&#xff08;BigModel&#xff09;提供了强大的工具和API&#xff0c;使得这一目标变得更加容易实现。 语言模型的力量 语言模型是智能对话系统的核心&am…

git分支-创建、合并、删除

Git会将每次提交串成一条时间线&#xff0c;这条时间线就是一个分支。在最初&#xff0c;只有一个master分支 在目录下创建项目 对目录进行输入 项目被修改 创建dev分支 合并分支 删除dev分支

maven项目自动reload依赖库设置

修改后&#xff0c;自动reload 不需要点加载按钮了。

牛客SQL练习详解 04:多表查询

牛客SQL练习详解 04&#xff1a;多表查询 1、子查询sql21 浙江大学用户题目回答情况 2、链接查询sql22 统计每个学校的答过题的用户的平均答题数sql23 统计每个学校各难度的用户平均刷题数sql24 统计每个用户的平均刷题数 3、组合查询sql25 查找山东大学或者性别为男生的信息 叮…

大数据新视界 --大数据大厂之Cassandra 分布式数据库在大数据中的应用与调优

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

常用激活函数总结

文章目录 什么是激活函数激活函数的作用常用激活函数1.Sigmoid函数2.Softmax函数3.Tanh函数4.Relu函数5.LeakyRelu函数6.PRelu函数7.ELU函数8.SELU函数 什么是激活函数 激活函数&#xff0c;通俗讲&#xff0c;就是一个函数&#xff0c;针对某个神经元&#xff0c;就是将输入经…