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

前面第九章介绍了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.mzph.cn/web/53989.shtml

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

相关文章

了解针对基座大语言模型(类似 ChatGPT 的架构,Decoder-only)的重头预训练和微调训练

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 随着自然语言处理&#xff08;NLP&#xff09;技术的飞速进步&#xff0c;基于 Transformer 架构的大语言模型在众多任务中取得了显著成就。特别是 Decoder-only 架构&#xff0c;如 GPT 系列模型&…

【UI】Vue3 + Naive-ui 使用表格Data Table 以及分页页码显示不全问题解决

参考文章&#xff1a; Vue3 Naive-ui Data Table 分页页码显示不全 Naive UI之数据表格分页pagination 数据列表分页全部代码: <n-data-tableref"tableRef"striped:columns"columns":pagination"pagination":bordered"false":d…

Java必修课——Spring框架

目录 一、Spring框架概述二、IOC概念和原理2.1、什么是IOC2.2、IOC接口 三、深入理解Java基础中的集合框架3.1、Collection3.2、Map3.3、集合工具类 四、练习写一个SpringMVC框架1、介绍2、程序实践3、总结 五、Java开发者必备10大数据工具和框架 一、Spring框架概述 Spring是…

Javase学习day1-前置知识

1、什么是计算机 2、 硬件及冯诺依曼结构 3、软件及软件开发 4、常用的快捷键 5、常用的Dos命令 常用的Dos命令&#xff1a;(基本都是在cmd里面写的) #盘符切换&#xff1a;直接输入那个盘符的名字加一个冒号就行。 #切换目录&#xff1a; cd change directory&#xff08;这是…

STM32编码器接口笔记

1. 引言 在现代控制系统中&#xff0c;编码器扮演着非常重要的角色。它就像一个精密的测量工具&#xff0c;可以告诉我们机械部件的位置和运动状态。在STM32微控制器中&#xff0c;编码器接口可以轻松地与各种编码器连接&#xff0c;实现精确的控制。我将在这里探讨STM32编码器…

ISA-95制造业中企业和控制系统的集成的国际标准-(2)

ISA-95 文章目录 ISA-95ISA-95企业层和制造运营管理层信息模型一、企业层和制造运营管理层信息模型内容二、企业层和制造运营管理层信息模型分类 ISA-95企业层和制造运营管理层信息模型 ISA-95信息模型是指ISA-95制造业中企业和控制系统集成的国际标准定义了企业层和制造运营层…

心觉:运用吸引力法则和开发潜意识的核心中的核心是什么?

吸引力法则的核心在于 思想的力量 和 频率的匹配。你所思考和感受的会吸引与你频率相匹配的事物和经历到你的生活中。具体来说&#xff1a; 明确意图和目标&#xff1a;清晰地知道你想要什么&#xff0c;并且用详细的方式描述它。这可以是通过写下目标、制作愿景板&#xff08;…

MySQL_视图

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

鸿蒙harmonyos next flutter通信之MethodChannel获取设备信息

本文将通过MethodChannel获取设备信息&#xff0c;以此来演练MethodChannel用法。 建立channel flutter代码&#xff1a; MethodChannel methodChannel MethodChannel("com.xmg.test"); ohos代码&#xff1a; private channel: MethodChannel | null nullthis.c…

PostgreSQL数据库与PostGIS在Windows中的部署与运行

本文介绍在Windows电脑中&#xff0c;下载、安装、部署并运行PostgreSQL与PostGIS数据库服务的方法。 PostgreSQL是一种功能强大的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;以其稳定性、可靠性和丰富的功能而闻名&#xff1b;其支持多种高级特性&…

新能源汽车储充机器人:能源高效与智能调度

新能源汽车储充机器人&#xff1a;开启能源高效利用与智能调度的未来之门 随着全球能源危机的日益加剧和环境污染问题的不断恶化&#xff0c;新能源汽车成为了未来交通领域的重要发展方向。然而&#xff0c;新能源汽车的普及不仅需要解决电池技术的瓶颈&#xff0c;还需要构建一…

【预备理论知识——1】深度学习:概率论概述

简单地说&#xff0c;机器学习就是做出预测。 概率论 掷骰子 假设我们掷骰子&#xff0c;想知道看到1的几率有多大&#xff0c;而不是看到另一个数字。 如果骰子是公平的&#xff0c;那么所有六个结果{1,…, 6}都有相同的可能发生&#xff0c; 因此我们可以说 1 发生的概率为1…

基于开源WQ装备知识图谱的智能问答优化2

基于笔者之前写的博客基础上&#xff1a;https://blog.csdn.net/zhanghan11366/article/details/142139488【基于开源WQ装备知识图谱的智能问答全流程构建】进行优化。新增处理基于特定格式下的WQ文档&#xff0c;抽取文档的WQ属性和关系&#xff0c;并抽取对应WQt图片存储至mi…

AIGC教程:如何用Stable Diffusion+ControlNet做角色设计?

前言 对于生成型AI的画图能力&#xff0c;尤其是AI画美女的能力&#xff0c;相信同行们已经有了充分的了解。然而&#xff0c;对于游戏开发者而言&#xff0c;仅仅是漂亮的二维图片实际上很难直接用于角色设计&#xff0c;因为&#xff0c;除了设计风格之外&#xff0c;角色设…

大数据开发--1.2 Linux介绍及虚拟机网络配置

目录 一. 计算机入门知识介绍 软件和硬件的概述 硬件 软件 操作系统概述 简单介绍 常见的系统操作 学习Linux系统 二. Linux系统介绍 简单介绍 发行版介绍 常用的发行版 三. Linux系统的安装和体验 Linux系统的安装 介绍 虚拟机原理 常见的虚拟机软件 体验Li…

RocketMQ消息发送之广播模式

前言 在前面的文章中我们回顾了RocketMQ的顺序消息和乱序消息&#xff0c;以及里面包含的乱序消息和全局消息&#xff0c;RocketMQ支持多种消息类型和消费模式 今天这篇文章主要介绍RocketMQ的广播消息。希望文章能为正在学习RocketMQ相关知识的大佬们提供帮助&#xff01; 广…

万博智云CEO王嘉在华为全联接大会:以创新云应用场景,把握增长机遇

一、大会背景 2024年9月19-21日&#xff0c;第九届华为全联接大会将在上海世博展览馆和上海世博中心举办。作为华为的旗舰盛会&#xff0c;本次大会以“共赢行业智能化”为主题邀请了众多思想领袖、商业精英、技术专家、合作伙伴、开发者等业界同仁&#xff0c;从战略、产业、…

【Y004】基于springboot+vue实现的图书管理系统

主营内容&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app等设计与开发。 收藏点赞不迷路&#xff0c;关注作者有好处 项目描述 (1) 图书信息的管理&#xff0c;包括图书信息的条件查询、录入、修改和删除。 (2) 图书类…

《MATLAB项目实战》,专栏目录和介绍

文章目录 前言专栏介绍&#x1f393;一、 项目实战篇和GUI界面篇&#x1f393;二、 项目基础篇总结 前言 MATLAB 是一款强大且广泛应用的数值计算和数据可视化软件工具&#xff0c;它提供了一个高效、简洁的编程环境&#xff0c;使用户能够进行从简单的矩阵运算到复杂的多维数…

理解Python闭包概念

闭包并不只是一个python中的概念&#xff0c;在函数式编程语言中应用较为广泛。理解python中的闭包一方面是能够正确的使用闭包&#xff0c;另一方面可以好好体会和思考闭包的设计思想。 1.概念介绍 首先看一下维基上对闭包的解释&#xff1a; 在计算机科学中&#xff0c;闭包…