实验环境:ubuntu 12.04 LTS

内核版本:linux-3.9.4

因为一直以来都对Linux的工作机理比较感兴趣,所以正好这两天有机会好好的研究一下,那闲话不多说,直接进入正题。

俗话说的好,公欲善其事,必先利其器。那么对于一个系统内核级的修改与研究必然不能从自己机器中正在运行的内核下手,这样一旦发生错误,将导致内核崩溃,无法启动,这个后果稍微有些严重。所以重新编译一个用于实验的内核是非常必要的。这里详见Linux学习之内核编译与添加系统调用。

对于本次的任务,一个模拟器也是非常必要的,这里主要是采用qemu模拟器。这个模拟器在linux下很常用,这里不再赘述。

当编译内核与安装qemu模拟器完成后,就可以正式开始本次任务之旅了。

因为内核已经编译结束,我们现在首先要做的是为我们自己的Linux系统准备一个非常重要的部分——根文件系统。这里主要采用了两种方案。

方法一:

首先建立目标根目录映像:

dd if=/dev/zero of=myinitrd.img  bs=4096 count=1024

dd 是 Linux/UNIX 下的一个非常有用的命令,作用是用指定大小的块拷贝一个文件,并在拷贝的同时进行指定的转换。dd 的主要选项:

1、指定数字的地方若以下列字符结尾乘以相应的数字: b=512, c=1, k=1024, w=2, xm=number m
2、if=file     输入文件名,缺省为标准输入。
3、of=file    输出文件名,缺省为标准输出。
4、ibs=bytes     一次读入 bytes 个字节(即一个块大小为 bytes 个字节)。
5、obs=bytes    一次写 bytes 个字节(即一个块大小为 bytes 个字节)。
6、bs=bytes      同时设置读写块的大小为 bytes ,可代替 ibs 和 obs 。
7、cbs=bytes     一次转换 bytes 个字节,即转换缓冲区大小。
8、skip=blocks    从输入文件开头跳过 blocks 个块后再开始复制。
9、seek=blocks     从输出文件开头跳过 blocks 个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)
10、count=blocks     仅拷贝 blocks 个块,块大小等于 ibs 指定的字节数。
11、conv=conversion[,conversion...]     用指定的参数转换文件。
       
        mkfs.ext3 myinitrd.img
        这句命令的意思是将之前建立的.img文件块格式化为ext3的文件格式。
        然后创建rootfs目录,作为一个空的挂载点,并将我们之前创建并格式化为ext3文件系统格式的映像文件挂载到rootfs目录下。
        mkdir rootfs
        sudo mount -o loop myinitrd.img rootfs
        这里的这一挂载使我们可以在后面对创建的ext3文件系统映像进行相应的操作。
        然后创建一个我们自己的init程序,这里要明确一个概念,在linux操作系统系统启动的过程中,当init进程挂载完实际的文件系统之后,会判断是否有用户指定的启动参数“init=”,若没有,则执行以下命令之一,/sbin/init,/etc/init,/bin/init,/bin/sh。这里我们创建自己的init程序就是作为用户指定的启动程序。
       
        可以看到init程序的主要任务是输出两句话。
        然后使用静态链接的方法编译成可执行文件,并将这一可执行文件拷贝到目标根目录下,即rootfs下。
        gcc -static -o init init.c
        cp init rootfs/
        然后准备dev目录,这里/dev目录下主要是包含了linux启动过程中所必需的设备文件。
        sudo mkdir rootfs/dev
        sudo mknod rootfs/dev/console c 5 1
        sudo mknod rootfs/dev/ram b 1 0
        其中console控制台设备就是那套直接连接在电脑上的键盘和显示器,是直接和计算机相连接的原生设备。另外控制台也包括虚拟控制台,总之,这是linux启动过程中必不可少的设备。ram在这里是作为linux的根设备所创建和挂载的。
        因为在之前已经将我们所创建的ext3文件系统格式的文件系统映像挂载到了rootfs目录下,所以上述这些操作,实际上都是针对myinitrd.img这一我们自己的根文件系统映像进行的操作。然后卸载。
        sudo umount rootfs
        至此,一个包含简单应用程序的根目录映像myinitrd.img就准备好了。
        然后使用之前安装好的qemu模拟器进行模拟,看看我们自己的linux操作系统能否正常启动。
        qemu -kernel linux-3.9.4/arch/x86/boot/bzImage -initrd myinitrd.img -append "root=/dev/ram init=/init"
        可以看到qemu中-kernel参数指定的是我们自己的Linux操作系统的内核映像的位置,即之前我们所编译的内核的bzImage的绝对路径,然后通过-initrd参数来指定我们自己的根目录映像,在-append参数中指定我们的根设备是/dev/ram,指定启动参数为用户指定的启动程序init。运行结果如下:
       
        可以看到我们自己的init程序作为用户指定的启动参数成功被init进程所执行,至此,采用方法一制作的根文件系统成功挂载。

方法二:

方法二采用的方法是通过使用busybox制作根文件系统。

首先下载busybox源码,并解压缩。

http://busybox.net/downloads/busybox-1.19.3.tar.bz2

然后进入busybox-1.19.3目录下,对busybox进行配置编译。

make defconfig

make menuconfig

这里要修改如下配置:

将busybox settings -> build options -> build busybox as a static binary这一项选上。

make

然后准备根目录映像,并安装busybox到根目录映像中。

dd if=/dev/zero of=busyboxmyinitrd12M.img bs=4096 count=3072

mkfs.ext3 busyboxmyinitrd12M.img

mkdir rootfs

sudo mount -o loop busyboxmyinitrd12M.img rootfs

cd busybox-1.19.3

sudo make CONFIG_PREFIX=../rootfs/  install

sudo umount rootfs

至此我们自己的通过busybox制作的根目录映像已经做好了,使用qemu模拟器试着运行一下。

qemu -kernel linux-3.9.4/arch/x86/boot/bzImage -initrd busyboxmyinitrd12M.img -append "root=/dev/ram init=/bin/ash"

运行结果如下:

可以看到进入到了busybox提供的shell环境,因此根文件系统加载成功。

到此为止,我们可以把前面的工作都看作是准备工作,真正精彩的节目开始了。

下面我们将制作带grub启动的磁盘映像。

首先获得grub并制作grub启动软盘。

下载grub,解压缩。

ftp://alpha.gnu.org/gnu/grub/grub-0.97-i386-pc.tar.gz

建立启动软盘映像:

dd if=/dev/zero of=vampirem.img bs=512 count=2880

添加grub启动功能

sudo losetup /dev/loop3 vampirem.img

sudo dd if=./grub-0.97-i386-pc/boot/grub/stage1 of=/dev/loop3 bs=512 count=1

sudo dd if=./grub-0.97-i386-pc/boot/grub/stage2 of=/dev/loop3 bs=512 seek=1

sudo losetup -d /dev/loop3

关于losetup命令的详细情况请参阅losetup命令和loop设备的使用

这里实际上是相当于采用一个循环设备loop3作为一个中间的挂载点,来对我们自己的grub软盘映像vampirem.img进行相应的修改和操作。

然后在qemu模拟器上测试一下,看是否可以进入grub界面。

  qemu -fda vampirem.img

OK,我们看到grub界面成功启动了。

接下来,开始准备我们自己的linux操作系统的磁盘映像。

dd if=/dev/zero of=40M.img bs=4096 count=10240

sudo losetup /dev/loop3 40M.img

然后要在磁盘映像上建立一个启动引导分区,这里采用

sudo fdisk /dev/loop3

可以看到m命令是察看帮助信息的,我们察看一下

然后看到n命令是新建一个分区,a命令是将这个分区设为引导分区,p命令是打印出分区表,w命令是把分区表写到磁盘上并退出。于是:

分区建好之后,将活动分区格式化为ext3fs文件系统格式,并挂载到rootfs目录下。

sudo losetup -d /dev/loop3

sudo losetup -o 1048576 /dev/loop3 40M.img

这里的偏移值1048576是因为之前在设置分区时我们可以看到第一个扇区是在2048处,因此2048*512=1048576便是此处的偏移值。

sudo mkfs.ext3 /dev/loop3

sudo mount -o loop /dev/loop3 rootfs/

然后把之前准备好的,文件系统映像文件和内核映像文件拷贝到rootfs目录下,即拷贝到我们的磁盘映像文件中。

sudo cp busyboxmyinit12M.img rootfs/

sudo cp linux-3.9.4/arch/x86/boot/bzImage rootfs/

然后在rootfs下建立boot目录,以及boot目录下的grub目录。

sudo mkdir rootfs/boot

sudo mkdir rootfs/boot/grub

然后将之前下载的grub的boot/grub目录下的文件拷贝到rootfs/boot/grub目录下。

sudo cp ./grub-0.97-i386-pc/boot/grub/* rootfs/boot/grub

然后需要在rootfs/boot/grub目录下建立一个启动菜单文件menu.lst。具体内容如下:

里面的内容意思很明显,这里不再赘述。

sudo umount rootfs

sudo losetup -d /dev/loop3

下面紧张的时刻到了,我们看一下,能否利用grub启动软盘,在磁盘映像上添加grub功能。

qemu -boot a -fda vampirem.img -hda 40M.img

可以看到,成功添加。

下面测试一下,从刚才制作好的我们自己的linux操作系统的磁盘映像文件进入grub界面然后启动。

qemu -hda 40M.img

至此,我们自己的一个小型的LINUX操作系统就完成了~

Linux学习之系统的构建的更多相关文章

  1. Linux学习之系统时间同步

    一.系统时间的设置 在Linux中设置系统时间,可以用date命令: //查看时间 [root@localhost ~]# date 2008年 12月 12日 星期五 :: CST //修改时间 [ ...

  2. linux 学习随笔-系统日常管理常用命令

    1:W 查看系统整体负载,无法查看具体负载,比如内存,磁盘  23:25:20 up 13 min,  2 users,  load average: 0.00, 0.01, 0.01 USER   ...

  3. Linux 学习笔记 1 使用最小的系统,从分区安装系统开始

    我们常用的linux系统在安装过程中大多都省略了对系统进行分区的操作,以至于后期,不了解什么是分区以及分区当中最基本的一些概念, 我们不说最细的知识,只求了解这个过程,那直接步入正题,开始第一节的学习 ...

  4. 嵌入式linux系统的构建

    前期工作:a.配置好tftp服务器:在嵌入式的童年中有介绍 b.开发板可以pc,linux 三者可以互相ping通 c.配置好nfs服务器:同样在嵌入式的童年中有介绍 一.嵌入式linux内核的制作( ...

  5. Linux学习之Centos(三)------系统文件目录及含义详解

    Linux学习之Centos 之三------文件目录及含义 在了解了每个文件的相关种类与属性,以及了解了如何更改文件属性/权限的相关信息后,再来要了解的就是, 为什么每套Linux distribu ...

  6. Linux学习笔记-Linux系统简介

    Linux学习笔记-Linux系统简介 UNIX与Linux发展史 UNIX是父亲,Linux是儿子. UNIX发行版本 操作系统 公司 硬件平台 AIX IBM PowerPC HP-UX HP P ...

  7. Linux学习之三-Linux系统的一些重要配置文件

    Linux学习之三-Linux系统的一些重要配置文件 1.网卡配置文件 /etc/sysconfig/network-scripts/ifcfg-eth0 说明: DEVICE=eth0        ...

  8. Linux学习之二-Linux系统的目录结构

    Linux学习之二-Linux系统的目录结构 在Linux的根目录下,有很多的目录,但是需要记住,对于Linux而言,一切皆文件.因此此处的目录也是文件.用ls / 命令就能看到根目录下的各类不同的目 ...

  9. Linux学习笔记(七) 查询系统

    1.查看命令 (1)man 可以使用 man 命令名称 命令查看某个命令的详细用法,其显示的内容如下: NAME:命令名称 SYNOPSIS:语法 DESCRIPTION:说明 OPTIONS:选项 ...

随机推荐

  1. C++语言笔记系列之十二——C++的继承

    C++的继承 1.继承方式 public(公有继承) 派生类中的成员能够訪问基类的public成员和protected成员,但不能訪问基类的private成员. 派生类的对象仅仅能訪问基类的publi ...

  2. Fckeditor用法

    试Fckeditor版本号:2.6.3 眼下Fckeditor仅仅能用于基于ie内核的浏览器,假设要使用于chrome等浏览器,请使用ckeditor. 详细用法: 1.将解压后的fckeditor整 ...

  3. Swift 简简单单实现手机九宫格手势密码解锁

    原文:Swift 简简单单实现手机九宫格手势密码解锁 大家可以看到我之前的文章[HTML5 Canvas简简单单实现手机九宫格手势密码解锁] 本文是使用苹果语言对其进行了移植 颜色配色是拾取的支付宝的 ...

  4. 省钱加油(Fuel Economy)题解

    题目 农夫约翰决定去做一个环游国家旅行,为了不让他的奶牛们感到孤单,于是他决定租一辆货车带领他的奶牛们一起去旅行.这辆货车的油箱最多可以承载G 个单位的油,同时为了简化问题,规定每一个单位的油可以行使 ...

  5. Android-Universal-Image-Loader学习笔记(两)--LruDiscCache

    最近最少使用缓存官员最近(LruDiscCache)之前,引入一个概念,一个重要的三个班: key:这是DiscCacheAware接口save里面的方法imageUri通过调用参数FileNameG ...

  6. DataTable相关操作,筛选,取前N条数据,获取指定列数据

    DataTable相关操作,筛选,取前N条数据,获取指定列数据2013-03-12 14:50 by Miracle520, 2667 阅读, 0 评论, 收藏, 编辑 1 #region DataT ...

  7. 快速构建Windows 8风格应用12-SearchContract概述及原理

    原文:快速构建Windows 8风格应用12-SearchContract概述及原理 本篇博文主要介绍Search Contract概述.Search Contract面板结构剖析.Search Co ...

  8. ASP.NET 5 Overview

    ASP.NET 5概观 (ASP.NET 5 Overview) http://www.asp.net/vnext/overview/aspnet-vnext/aspnet-5-overview AS ...

  9. .NET Reflector 7.6.1.824安装及破解(刚试了,绝对能用)

    首先下载在这里http://download.csdn.net/detail/gattaca2011/4578752,不要到官网去了,由于官网已经是8.0了. 然后就是安装,执行注冊机(注意断网),详 ...

  10. Oracle笔试题库 附参考答案

    1.  下列不属于ORACLE的逻辑结构的是(C) 区 段 数据文件 表空间 2. 下面哪个用户不是ORACLE缺省安装后就存在的用户(A) A . SYSDBA B. SYSTEM C. SCOTT ...