当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]软盘上的Linux系统方案

本文将介绍一种两张软盘上的Linux系统,它可以当作系统应急修复盘、路由器或防火墙等许多地方,通过对它的研究,也可以加深对嵌入式系统的理解。
  
  一.前言

  嵌入式Linux是由一个几百KB的Linux内核和一个根据需要制定的文件系统所构成了, 由于Linux是开放源代码的操作系统,所以在嵌入式领域有着非常广阔的前景,并已经广泛应用在许多手机、PDA、MP3播放器等许多电子产品中。本文将介绍一种两张软盘上的Linux系统,它可以当作系统应急修复盘、路由器或防火墙等许多地方,通过对它的研究,也可以加深对嵌入式系统的理解。 
  
  二.Linux启动过程

  所有的PC机在加电之后,BIOS会寻找到启动盘第一个扇区,并将其复制到RAM中来执行它,对于两种不同的启动方式,这个扇区通常含有两种不同的代码:引导程序(比如Lilo或Grub等)的代码,引导程序会帮助定位内核的位置。内核的代码,这通常是从软盘启动时使用的引导的方式。对于前者,通常需要内核支持initrd。如果是后者,使用的Boot Loader就是arch/i386/boot/bootsect.S。当内核被编译的时候,这段执行代码就被链接到内核image的最开始的地方。这样很容易就能只要把内核复制到起始位置为第一个扇区的软盘上就能得到可自启动的软盘。内核会初始化设备驱动和内部的数据结构,之后它会到一个特定的位置――Ramdisk Word来获得根文件系统的位置。内核必须知道去那里寻找这个根文件系统,否则它将停机。 
  
  在使用软盘启动的方式时,内核可以把一个压缩的文件系统释放到RAM中,称之为Ramdisk,这是一个内存区域,但内核会把它当作磁盘一样使用。 
  
  本文中介绍的例子使用Grub做为引导程序,并使用initrd来辅助Linux的启动。两张软盘分别命名为bootldr盘和rootfs盘,在bootldr盘中内容为grub、内核、initrd,rootfs盘中是压缩过的根文件系统。系统启动时bootldr盘的Grub定位并执行内核,然后内核解开initrd,并执行linuxrc文件,这个文件负责提示用户更换rootfs盘并将其中内容解压至内存中,然后执行刚刚解压的init继续启动过程。 
  
  为了方便理解这个例子,先介绍目录结构如下: 
  
  /home/papaya
  ├─bootldr/
  │ ├─grub/
  │ ├─kernel/
  │ │ ├─images/
  │ │ └─linux-2.4.21/
  │ └─initrd/
  │   ├─mkinitrd.sh
  │   ├─local/
  │   └─ramdisk/
  ├─rootfs/
  │ ├─mkrootfs.sh
  │ ├─ramdisk/
  │ └─local/
  └─lib/

  三.定制Grub引导程序

  插入一张软盘,然后将其格式化,然后加载到/mnt/floppy 
  
  #mke2fs /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中,然后在/mnt/floppy/boot/grub目录下创建grub.conf文件: 
  
  default=0
  timeout=10
  title Floppy Linux
  kernel (fd0)/bzImage root=/dev/ram0 
  initrd (fd0)/initrd.gz 
  
  然后创建一个链接 
  
  #ln -s grub.conf menu.lst 
  
  执行 
  
  /sbin/grub --batch --device-map=/dev/null <  device (fd0) /dev/fd0
  root (fd0)
  setup (fd0)
  quit
  EOF 
  
  这样grub就被安装到bootldr盘上了。 
[!--empirenews.page--]四.定制Linux内核

 

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

  在initrd/local目录下建立bin, dev, etc, lib, proc, sysroot, usr目录。其中dev目录下包括必要的设备文件,比如tty, ram, console等等, bin中必要的可执行文件有bzip2, chroot, cp, cpio, dd, echo, mount, pivot_root, readkey, sh, test等。Busybox提供了其中大部分。 bzip2, dd, cpio用来解压缩第二张软盘上的内容,chroot, pivot_root用来转换根目录。 
  
  编辑initrd/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 | bzip2 -d | cpio -idv 
  
  下面将initrd中的文件copy到sysroot/bin目录下,这样可以把根文件系统中一部分内容放到initrd(第一张软盘)中,因为软盘容量有限,当第一张软盘空间有剩余,而第二章软盘空间紧张的时候这会非常有用。 
  
  echo "Copying:"
  for file in bzip2 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 2>&1
  
  echo -en"Something went wrong ..."
  /bin/sh || /mnt/initrd/bin/sh 
  
  当initrd所有必须的文件都放到bootldr/initrd/local目录下之后,就可以执行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 /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盘就完成了。 
  
  六.定制根文件系统

  一个根文件系统需要包含支持Linux系统运行的所有文件。通常包括: 
  
  基本的文件系统结构 
  
  基本的目录: /dev, /proc, /bin, /sbin, /etc, /usr, /tmp等。 
  
  基本的工具: 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中。 
  
  在rootfs/local中在自己创建下面几个目录:dev/, tmp/, etc/, proc/ 
  
  可以将系统中/dev下的设备复制到这个目录下,只需要复制必要的就可以了,例如: 
  
  #cp -dpR /dev/tty[0-9] /mnt/rootfs/dev
  #cp -dpR /dev/ram* /mnt/rootfs/dev 
  
  但是要注意一定要包含必要的接各设备/dev/console, /dev/kmem, /dev/mem, /dev/tty, /dev/ram0, /dev/null等。 
  
  etc/目录下包含了目标系统运行所必须的配置文件,它包括的内容依赖与目标系统所要运行的程序。最低限度,它包括下面几个文件:inittab、rc、fstab、passwd、group、shadow、termcap等。做为init进程的参数,inittab可以非常简单,仅需要包括下面几行即可: 
  
  ::sysinit:/etc/rc
  ::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 
  
  其中sysinit指明系统初始化脚本rc。rc所包含内容也可以非常少: 
  
  #!/bin/sh
  /bin/mount -av
  /bin/umount /mnt/initrd
  /bin/hostname papaya 
  
  fstab的内容为: 
  
  none /proc proc defaults 0 0
  none /tmp tmpfs defaults 0 0 
  
  其他的配置文件可以从原来的系统中获得,然后修剪掉不必要的内容即可。 
  
  现在在/mnt/rootfs中已经包含了运行一个最低限度Linux系统所必须的所有文件和工具,下面需要将它们压缩成一个文件系统了。插入rootfs软盘并执行bootldr/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 ..
  bzip2 rootfs.cpio
  umount ramdisk
  dd if=rootfs.cpio.bz2 of=/dev/fd0 bs=1k 
  
  OK,rootfs盘也完成了,可以重启机器验证了。 
[!--empirenews.page--]七.其他方法

 

  将内核与文件系统进行整合,如果不用Grub引导还有两种选择,不过根文件系统就不能象上面那样打包再压缩, 也不再使用initrd。把所有根文件系统文件放到一个目录中(比如上面的rootfs/local),然后执行 
  
  dd if=/dev/zero of=/dev/ram0 bs=1k count=4096
  mke2fs /dev/ram0
  mount -t ext2 /dev/ram0 ramdisk/
  cp -R local/* ramdisk/
  umount ramdisk
  dd if=/dev/ram0 bs=1k | gzip -v9 > rootfs.gz 
  
  1.将内核与文件系统放置在一张软盘上 
  
  确定内核的大小和的大小之合没有超出软盘的限制。记住内核的大小,然后将内核写到软盘上: 
  
  #dd if=bzImage of=/dev/fd0 bs=1k
  353+1 records in
  353+1 records out 
  
  之后,设置根设备为软盘本身,并且设置根以读写方式装载 
  
  #rdev /dev/fd0 /dev/fd0
  #rdev -R /dev/fd0 0 
  
  上面这个例子表示dd写了353个完整记录和一个部分记录到软盘上,因此内核占用了软盘的前354个记录块。记住这个数字,然后设置内核的Ramdisk Word。Ramdisk Word可以通过rdev命令设置,它的内容为:


  如果15位设置的话,内核在加载文件系统之前会进行提示,这在下面将内核与文件系统盘分开的情况时是必要的。" 
  
  对于上面的情况,需要在0-10位指出ramdisk的偏移,并将14位置1,所以得出的ramdisk word十进制表示为:355 + 2^14 = 355 + 16384 = 16739 
  
  #rdev -r /dev/fd0 16739 
  
  之后 
  
  #dd if=rootfs.gz of=/dev/fd0 bs=1k seek=354 
  
  这样一张同时包含内核和文件系统的软盘就成功了。 
  
  2.内核与文件系统分别占用一张软盘 
  
  与上面一样 
  
  #dd if=bzImage of=/dev/fd0 bs=1k
  #rdev /dev/fd0 /dev/fd0
  #rdev -R /dev/fd0 0
  不同的是ramdisk word为 0 + 2^14 + 2^15 = 49152
  #rdev -r /dev/fd0 49152
  然后换零一张软盘
  #dd if=rootfs.gz of=/dev/fd0 bs=1k 
  
  内核、根文件系统、引导程序之间的整合方法有很多,他们各有各自的特点,有待读者自己思考。 
  
  八.前景

  按照本文方法所构造的Linux系统虽然还不完善,但通过逐步的改进,将能做出一个有价值的系统来。真正的Linux嵌入式系统根据不同的应用方向通常还包括图形用户界面或者是网络浏览器等应用程序。值得庆幸的是很多OpenSource的项目提供了所需要的组件,结合这些优秀的开源项目,就可以形成一套真正的嵌入式Linux操作系统。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭