基于CF卡的 linux系统制作由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“linux根文件系统制作”。
在CF卡上安装嵌入式linux全过程
吴刚 2007-4-4 摘要:本文主要介绍在一块128M的CF卡上定制安装linux操作系统,并在此基础上建立一个简单的应用平台。
关键词:extlinux,busybox, CF卡,嵌入式linux
随着信息技术和网络技术的高速发展,嵌入式技术的广泛应用,嵌入式系统已经打破传统PC工业的垄断地位,成为非PC设备的主体。而作为嵌入式系统,应用环境通常比较恶劣,而应用又比较简单,为保证系统的稳定性和便携性通常使用DOM卡或CF卡一类的存储设备来代替硬盘。
经过一段时间的摸索和收集资料终于在一块CF卡上实践安装了一个满足特定需要的嵌入式linux系统,这里取名为cflinux.在这里首先要感谢《babylinux制作全过程的》作者,正是这片文章,为我制作cflinux指明了道路。本文将讲述在一张容量为128M的CF卡上定制安装嵌入式linux操作系统的详细过程,一 主机和目标机情况简介
主机:
Linux:Red Hat 9.0 Kernel: 2.4.20 目标机:
基于X86的工控板
二 cflinux简介
cflinux是一运行于CF卡上的经过自定义剪裁的嵌入式linux操作系统。因其运行于CF卡上,故取名为cflinux.当此操作系统和应用环境搭建好后可以通过网络telnet和串口访问目标板,可运行QT/E图形界面应用程序。可以通过串口,网口和USB口和外围设备交互。既可作为嵌入式操作系统,也可作为启动盘作为系统维护工具。
三 linux得引导过程简介
在系统启动时,主板上的BIOS会读取硬盘的主引导记录(MBR),MBR中存放的是一段很小的程序,他的功能是从硬盘读取操作系统核心文件并运行,因为这个程序太小了,因此通常这个小程序不具备直接引导系统内核的能力,他先区引导另一个稍微大一点的小程序去引导系统内核。在linux系统中这样得小程序有LILO,GRUB和SYSLINUX等。我们在这个项目中这里用到的引导程序是SYSLINUX得一个分支:EXTLINUX。
Linux系统内核被引导程序装进内存并运行后,linux内核会检测系统中得各种硬件,并做好硬件得初始化工作,使他们在系统正式运行后能正常工作。剩下就是linux内核要做得最后一个工作:运行/sbin下得init程序。Init是英文单词(initialization)初始化得简称,init程序得工作是读取/etc/inittab文件中的指令,对系统的各种软硬件环境做最初的初始化工作,最后运行gettty活mingetty等待用户输入用户名和密码(当然根据需要也可以跳过登录这个步骤,直接以root身份登录)。所有的工作就是这么简单。明白了这个道理,你也可以写一些脚本程序让他在系统启动时的特定时间完成运行,完成你指定的任务。/sbin/init程序只是系统默认的运行的第一个程序,他可以是一个二进制程序也可以是一段bash脚本,一个指向另一个程序的链接。他的位置也并不一定在/sbin下,只要启动内核时加上init参数节能被运行,开始时给内核加上init=/bin/sh参数,内核就能直接运行时并给出提示符,不需要登陆。
四 extlinux安装
EXTLINUX是SYSLINUX的一个新的派生。可以从linux系统的ext2和ext3文件系统启动。EXTLINUX使用和SYSLINUX相似,只需做一点改动即可。首先从http://www.daodoc.com/pub/linux/utils/boot/syslinux/ 上下载syslinux-3.20.tar.gz。
cp syslinux-3.20.tar.gz /usr/tmp tar xzvf syslinux-3.20.tar.gz 进行解压。然后用IDE to CF转接卡把CF卡连到主机上(注意:一般CF卡是不支持热插拔的,故插上CF后一般需要重新启动主机系统)。我的CF卡对应的设备文件是hdd1.在这里先使用fdisk工具把CF卡分成两个区,一个用于存放内核和randisk,另一个用于存放应用程序及相关文件。Fdisk的使用可参见相关资料,这里不做详细说明。我的CF卡主分区为hdd1,扩展分区为hdd2,将所有的扩展分区都分给逻辑分区hdd5。分好区后,将hdd1 和 hdd5格式化为ext2系统 mke2fs –m 0 /dev/hdd1 mke2fs –m 0 /dev/hdd5 //-m 0参数的作用是告诉系统不为root保留空间 一切准备好后,就可以安装EXTKINUX了,安装步骤如下: mount –t auto /dev/hdd1 /mnt cd /usr/tmp/syslinux-3.20/extlinux./extlinux –i /mnt
安装成功后会提示extlinux 成功安装到/mnt,然后在/mnt目录下会出现extlinux.sys文件。
umount /mnt 至此extlinux已经安装完毕,可以把CF卡插到工控板上,上电启动一下看看有什么效果。如果安装成功的话,启动后会出现如下的提示:
EXTLINUX 3.20 2006-08-06 EBIOS Copyright(c)1994-2005 H.peter Anvin Could not finf kernel image:linux boot: 注:关于extlinux的详细使用方法,请参阅syslinux-3.20目录下的extlinux.doc文件
五 linux内核编译
在内核编译前,我们首先要明确你需要内核支持什么样的硬件,支持多少种分区类型和文件系统,支持那些网卡,支持那些网络协议等等。虽然现在有128兆的空间,但也不能什么都要,够用就行啊。好了,现在开始内核的编译工作。首先准备好内核代码,可以到官方网站上下载,我的内核源码是安装linux时带上的,在/usr/src/linux-2.4/目录下。cd /usr/src/linux-2.4 make mrproper 清理源码树 make menuconfig 然后对各项取舍如下:(至于具体配置项的意义,请参考相关资料,不在本文讨论范围之内)
code maturity level options 先不选,当我们配置好常规的东西,要加入framebuffer支持时再将这一项选上。因为在2.4.20版本中,对frambuffer的支持尚属于试验性代码,如果不选择此项将不能配置frambuffer.Load module support 取消选择此项,为了简化系统的制作,这个项目中将不选择可加载内核模块的支持。
Proceer type and features Proceor family中选择你需要的cpu类型,如果你想让老至386,新到p4的CPU都能运行cflinux的话,请选择386,否则根据实际情况来选择。建议选386。
General setup Networking support 都选上
PCI支持 选上,除非你不用PCI设备,不过一般人都要的,因为大部分的网卡都是PCI的。
System V ipc 选上 Systrl support选上
Kernel support for ELF 选上
其他内容如果没什么特殊需要,都不选。
Memory technology devices(MTD)不选
Parallel port support 由于本项目中需要使用并口打印机,故将此项选上
Plug and play configuration 不选
Block devices Normal floppy disk support 不选
Loopback device support RAM disk support Initial RAM disk(initrd)support Per partion statics in /proc/partions
以上几项都选上。由于这几项比较重要这里做详细说明。Loopback device 即回环设备,我们平时用的命令瓜子ramdisk或光盘镜像时都用到回环设备。如:mount –o loop ramdisk.img /mnt RAM disk support 即内存磁盘(比较贴切的说法是虚拟磁盘,即拨出一部分内存当磁盘用)。本项目中将所有系统的的文件都做成ramdisk,所以在运行时你在根文件系统上所作的操作都是在内存中完成的,但形式上和在真正的磁盘上运行一样。只不过放在RAM disk上的所有内容会在系统关闭后全部消失。
不仅在运行cflinux时用到ramdisk,我们在制作根文件系统时也用到ramdisk。学习ramdisk的使用也是制作cflinux的重要目标之一。在linux中还支持另外一种虚拟磁盘:shm.(shared memory),这种要虚拟磁盘机制比ramdisk更加先进。Ramdisk的大小是固定的,由编译内核时的default ram disk size决定,默认为4096K,因为本项目中要往ramdisk中放很多东西,故这里我们要将其改为8192K(8M)。也可以在内核加载钱加上ramdisk_size=参数来决定他的大小,但系统一启动,ramdisk的大小是不能改变的,而shm的大小却是动态改变的。默认情况下为物理内存的一半,当系统需要更多内存的时候,他就自动缩小。系统内存富余时,他又会自动增大,这样可以充分灵活的利用内存空间,shm通常作为磁盘的高速缓存,放在系统运行中的临时文件等。既然shm这么好,为什么这里还使用ramdisk呢,因为ramdisk可以很方便的在系统启动时加载,而shm则没那么容易。Initial RAM disk(initrd)support 即初始化ramdisk支持,这个选项让内核有能力在内核加载阶段就能装入RAMDISK,并运行其中的内容。否则只能在系统运行阶段用ramdisk,我们平时编译了一个内核后,如果你的根文件系统用的是ext3,而你没有把ext编译进内核,而作为一个模块编译了,那么就需要用mkinitrd命令做一个initrd,这个ramdisk里放了ext3的模块,这样内核在加载根文件系统前就能正确识别ext3系统,否则内核加载的最后一步就会出现kernel panic cant not find init„..的错误。
Per partion statics in /proc/partions 这个选项不是必须的,但是不把这个选项编译进内核在执行fdisk指令时就会提示找不到/proc/partions,另外还可能出现不能以简写的挂载命令来挂载文件系统。所以我把该选项也编译进内核。
Multi-device support(RAID and LVM)不选 Cryptography support(CryptoAPI)不选
Networking options 在这一大项中需要把下列项目编译进内核: Packet socket:mmapped IO TCP/IP networking 对于IP:advanced router 这项,如果你想重点把cflinux用做静态路由软件,那么把这项编译进去。另外unix domain sockets 这项也不必选择,只有运行X的情况下才需要这项。
Telephony support 不选
ATA/IDE/MFM/RLL support 选上,然后在下面的“IDE,ATA and ATAPI Block Devices”按钮就被激活,下面几项选上,其余都不用选
Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support Include IDE/ATA-2 DISK support Auto-Geometry Resizing support Include IDE/ATA CDROM support
SCSI support 因为这个项目中是通过CF卡启动的,所以把这项也选上。在这个大项中只需选择一下3项即可: SCSI disk support SCSI generic support SCSI tape support
Fusion MPT device support 不选 IEEE1394(FireWrite)support 不选
I2O device support 选上,子项全部选上 Network device support 选上,这样就可以支持网卡了,其余都选择N.然后点Ethernet(10 or 100 Mbit)按钮选择你 需要的网卡驱动,你可以把最常见的几种Reltek8139,NE2000,3COM等网卡编译进内核.虽然网卡的驱动通常都很小
如果你发现你需要的网卡是灰色的,不能点,那么先确定他上一级的选项已经点了,比如你想选NE2000的网卡,就必需先选择ELSA,VLB,PCI and on board controllers.如果还不能点,那么请确定是否已经把PCI的支持选项选上了,(在Geneal setup)里.没有PCI的支持,PCI的网卡将不能选.Amateur Radio support 不选 IrDA(infrared)support 不选 ISDN subsystem 不选
Old CD-ROM drivers(not SCSI,not IDE)不选
Import core support 因为本项目中要使用到键盘和鼠标,所以选上该项,其子项也全部选中。然后把Horizontal screen resoulution 改为 800,vertial scrren resoulution 改为600。
Character devices 这一项和block devices一样重要,这里将作重点讲述。
如果要在终端上显示系统信息就必须将virtual terminal 和support for console on virtual terminal 选上。因为本项目中防治系统信息覆盖掉QT的图形界面,所以没选这两项。
接下来就是对串口的指出。因为本项目中需要通过串口和并口与设备交互,故下面几项都要选上:
Standard(gtneric18250/16550 and compatible UARTs)serial support Support for console serial port Extended dumb serial driver options Support special multport boards Non-standard serial port support
Unix98 PTY support(telnetd 服务用到)Parallel printer support Support for console on line printer Support for user-space parallel device drivers
哈哈,下面的文件系统可是个重头戏哦,配置完这一项,整个内核配置也基本急速了。选上下面几个常用的文件系统选项: Kernel auto mounter support Kernel automounter version 4 support DOS FAT fs support MSDOS fs support UMSDOS:unix-like file system on top of standard MSDOS VFAT fs support EFS file system support /proc file system support 少了他很多软件和命令都不能运行 /dev/pts file system for unix98 PTYs telnetd服务用到 ROM file system support Second extended fs support cflinux的基本文件系统
最后是console drivers 这是linux在字符模式下高分辨率显示的内核模块,前面三个子项都选上。
Frame-buffer support 按钮是灰色的不能选,别急,回到第一个大项,选上他,然后在Frame-buffer support的子项中选上 Support for framebuffer devices VESA VGA granphics console 你也可以选择其他的显卡驱动,比如nVida的,但是VESA和VGA是通用性最好的,只要不是几十年前的黑白卡,都兼容VESA和VGA。Support only 8 pixels wide fonts 这个一定要选,否则当你给内核传递vga=768参数,让linux在字符界面下高分辨率显示的时候,系统会因为找不到合适的字体而返回低分辨率模式。
好了,所有的内核配置到这里就全部结速了,剩下的几个大项全部不用选。保存退出。make dep make baImage 编译好的内核放在:/usr/src/linux-2.4.20-8/arch/i386/boot目录下 将其拷贝到CF卡的主分区上: mount /dev/hdd1 /mnt cp /usr/src/linux-2.4.20-8/arch/i386/boot/bzImage /mnt
到此为止我们已经安装好了extlinux和内核编译,现在就可以试试刚编译的内核是否能启动了。不过首先要在bzImage所在的目录建立extlinux.conf配置文件,告诉extlinux在哪里寻找内核和ramdisk。extlinux.conf的格式如下: default emblinux display logo.txt label emblinux kernel bzImage append root=/dev/hdc1 initrd=ramdisk.img ide=nodma vga=0x0314 保存即可。注:在工控板上cf卡对应的设备是hdc所以这里用root=/dev/hdc1 指明根文件系统所在 initrd=ramdisk.img 指明ramdisk名称。
ide=nodma 告诉内核不使用DMA控制器,这是针对CF卡的一个选项。vga=0x0314 指明分辨率为800×600
执行 umount /mnt 卸载CF卡,然后将CF卡插到工控板上上电启动,看看是不是能看到系统内核启动信息了啊。
六 编译busybox 1 busybox简介
Busybox是一个集成一百多个最长用的linux命令和工具的软件,他甚至还集成了http服务器、dhcp服务器和telnet服务器,而所有这些功能却只有1M左右的大小。我们平时用的那些linux命令就好比分离的电子元件,而busybox就好比是一个集成电路,把常用的工具和命令集成压缩在一个可执行的文件里,功能基本不变,而大小却小很多倍,在嵌入式式linux中使用非常广泛。现在最新的busybox版本是1.5.0可以从busybox的官方网站上下载得到:http://www.daodoc.com> # # Note: BusyBox init doesn't support runlevels.The runlevels field is # completely ignored by BusyBox init.If you want runlevels, use # sysvinit.# # Format for each entry: :::
# # id == tty to run on, or empty for /dev/console # runlevels == ignored # action == one of sysinit, respawn, askfirst, wait, and once # proce == program to run
# Startup the system null::sysinit:/bin/mount-o remount,rw / null::sysinit:/bin/mount-t proc proc /proc null::sysinit:/bin/mount-a >> /etc/mtab null::sysinit:/bin/hostname-F /etc/hostname null::sysinit:/sbin/ifconfig lo 127.0.0.1 up null::sysinit:/sbin/ifconfig-a eth0 null::sysinit:/sbin/ifconfig eth0 192.168.4.44 netmask 255.255.255.192 null::sysinit:/sbin/route add-net 127.0.0.0 netmask 255.0.0.0 lo null::sysinit:/sbin/route add-net 192.168.4.0 netmask 255.255.255.255 eth0
# now run any rc scripts ::sysinit:/etc/init.d/rcS
# Set up a couple of getty's # 使用login登陆管理
tty1::respawn:/sbin/getty 38400 tty1 #不需要登陆直接进入控制台,进行操作 #tty1::respawn:/bin/sh
tty2::askfirst:/bin/sh
# Put a getty on the serial port #ttyS0::respawn:/sbin/getty-L ttyS0 115200 vt100
# Stuff to do for the 3-finger salute ::ctrlaltdel:/sbin/reboot ::restart:/sbin/init
# Stuff to do before rebooting null::shutdown:/bin/umount-a –r
pawd: root:x:0:0:root:/root:/bin/sh cf:x:1001:0:Linux User,,:/home/soullon:/bin/sh shadow: root::10933:0:99999:7::: cf::13604:0:99999:7::: 注意:这里两个用户都没设密码,如果要加密码胡话在用户名后的第一个“:”和第二个“:”之间加上密码胡hash值。如:
root:$1$NuFDgiiI$664QR8N4HSdgkUDKpxEB00:10933:0:99999:7:::
shadow-:
root::10933:0:99999:7::: cf::13604:0:99999:7:::
resolv.conf -> /tmp/resolv.conf
fstab: /dev/hdc1 / ext2 defaults 1 1 /dev/hdc1 / ext2 defaults 1 1 none /proc proc defaults 0 0 usbdevfs /proc/bus/usb usbdevfs rw 0 0 none /dev/pts devpts rw,gid=5,mode=620 0 0 none /tmp tmpfs defaults 0 0 /dev/hdc5 /myapp ext2 defaults 0 0
init.d(目录): rcS: #start inetd and telnetd /sbin/telnetd-p 23
#run myapp export QTDIR=/yysg export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/myapp/lib:/usr/lib cd /myapp./myapp –qws iue: Welcome to CFLinux
profile : # ~/.bashrc: executed by bash(1)for non-login interactive shells.export PATH= /bin: /sbin: /usr/bin: /usr/sbin: /usr/bin/X11: /usr/local/bin
# If running interactively, then: if [ “$PS1” ];then
if [ “$BASH” ];then
export PS1=“[u@h W]$ ”
alias ll='/bin/ls--color=tty-laFh'
n/ls--color=tty-F' export LS_COLORS='no=00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.png=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:';else if [ “`id-u`”-eq 0 ];then
export PS1='# ' else
export PS1='$ ' fi fi
export USER=`id-un` export LOGNAME=$USER export HOSTNAME=`/bin/hostname` export HISTSIZE=1000 export HISTFILESIZE=1000 export PAGER='/bin/more ' export EDITOR='/bin/vi' export INPUTRC=/etc/inputrc export DMALLOC_OPTIONS=debug=0x34f47d83,inter=100,log=logfile
### Some aliases alias ps2='ps facux ' alias ps1='ps faxo “%U %t %p %a” ' alias af='ps af' alias cls='clear' alias df='df-h' alias indent='indent-bad-bap-bbo-nbc-br-brs-c33-cd33-ncdb-ce-ci4-cli0-cp33-cs-d0-di1-nfc1-nfca-hnl-i4-ip0-l75-lp-npcs-npsl-nsc-nsob-n-ts4 ' #alias bc='bc-l' alias minicom='minicom-c on' alias calc='calc-Cd ' alias bc='calc-Cd ' fi;
inputrc: # /etc/inputrc-global inputrc for libreadline # See readline(3readline)and `info readline' for more information.# Be 8 bit clean.set input-meta on set output-meta on set bell-style visible
# To allow the use of 8bit-characters like the german umlauts, comment out # the line below.However this makes the meta key not work as a meta key, # which is annoying to those which don't need to type in 8-bit characters.# set convert-meta off
“e0d”: backward-word “e0c”: forward-word “e[h”: beginning-of-line “e[f”: end-of-line “e[1~”: beginning-of-line “e[4~”: end-of-line #“e[5~”: beginning-of-history #“e[6~”: end-of-history “e[3~”: delete-char “e[2~”: quoted-insert
# Common standard keypad and cursor #(codes courtsey Werner Fink,)#“e[1~”: history-search-backward “e[2~”: yank “e[3~”: delete-char #“e[4~”: set-mark “e[5~”: history-search-backward “e[6~”: history-search-forward # Normal keypad and cursor of xterm “e[F”: end-of-line “e[H”: beginning-of-line # Application keypad and cursor of xterm “eOA”: previous-history “eOC”: forward-char “eOB”: next-history “eOD”: backward-char “eOF”: end-of-line “eOH”: beginning-of-line
securetty: tty1 tty2 tty3 tty4 tty5 tty6 tty7 tty8 ttyS0 ttyS1 ttyS2 ttyS3
network(目录): interfaces: # Configure Loopback auto lo iface lo inet loopback
八 复制需要的库到/lib目录下
1 看看需要什么库
进入busybox编译目录,执行ldd指令看看需要哪些动态联结库 #cd /usr/tmp/busybox-1.5.0 #ldd busybox 会出现如下信息:
libcrypt.so.1-> /lib/libcrypt.so.1(0x40029000)libc.so.6-> /lib/tls/libc.so.6(0x42000000)/lib/ld-linux.so.2-> /lib/ld-linux.so.2(0x4000000)
2 拷贝库文件
然后把这些库文件相关联的库文件都拷贝到相应的目录:
#cd /usr/tmp/rootfs/lib #cp –arf /lib/libcrpt*./ #cp –arf /lib/ld-linux*./ #mkdir tls #cp –arf /lib/tls/libc.so*./tls/
如果你的应用程序还需要其他的动态库,且不是很大的话都可以放过来。
九 制作ramdisk映象文件
cflinux根文件系统需要的所有东西都已经在/usr/tmp/rootfs目录下准备好了。我们将利用ramdisk把这些内容做成ramdisk映象文件。
以下是ramdisk的制作过程。#cd /usr/tmp #mkdir ramdisk #dd if=/dev/zero of=./ramdisk.img bs=1M count=6 读入了 6+0个块
输出了 6+0个块
#mke2fs –m 0 ramdisk.img make2fs 1.32(09-Nov-2002)ramdisk.img is not a block special device Proceed anyway?(y,n)//输入y,按回车键
Filesystem label = OS type:Linux Block size=1024(log=0)1536 inodes ,6144blocks „„„„„„„„„„„„„„„„„„„„
180 days,whichever comes first.Use tune2fs –c or –I to overrite
zero是一个特殊的设备,表示全部为零的字符块。上面这条指令的意思是把系统的第一个ramdisk用全部为0的数据填充。Bs=1M 表示块的大小为1M,count=6 表示有6块。即我们监理了一个大小为6M的ramdisk.接下来就应该往ramdisk中填充文件了:
#mount –o loop ramdisk.img ramdisk #cp –arf rootfs/* ramdisk/ #umount ramdisk
做完以上几步,你就应该明白ramdisk设备的含义,他和hda1,hdb1,一样的块设备用mount挂到文件系统下后就可以访问,往里面放东西,但是所有的东西在内存上,关机将丢失所有东西。
十 系统整合前面已经做好了内核,安装好了extlinux,现在只需要把ramdisk放到bzImage 所 在的目录就可以了。
#mount /dev/hdd1 /mnt #cp ramdisk /mnt #umount /mnt 好了现在就可以把cf卡插到工控板上,试一把了。如果一切正常的话就可以进入登陆界面了,呵呵。
十一 移植应用程序
在本文开始的时候已经说过将操作系统文件放在cd卡的注分区上hdd1上,把应用程序放在逻辑分区hdd5上。因此我们将编译好的应用程序及其相关文件拷贝到hdd5上。由于应用程序用到的共享库不是固定的所以就没有将他们放到ramdisk中,直接和应用程序放在一起,只不过在系统启动后要将这个库目录加到系统库目录路径上即可。在这个项目中,我在hdd5上件了一个lib目录,然后把应用程序用到的库全部放在这个目录下面,然后在profile文件中增加一项两行就行: export LD_LIBRARY_PATH=#LD_LIBRARY_PATH:/myapp/lib export QTIDR=/myapp
十二 参考文献
《BabyLinux制作过程详解》作者:GuCuiwen email:win2linux@163.com