热门关键字:  ubuntu  分区  函数  Fedora  linux系统进程

学会做嵌入式Linux操作系统

来源: 作者: 时间:2007-05-31 Tag: 点击:

A、如果编译时选择了:

Runtime SUID/SGID configuration via /etc/busybox.conf

系统每次运行命令时,都会出现“Using fallback suid method ”

可以将它去掉,不过我还是在/etc为其建了一个文件busybox.conf搞定;

B、 [*] Do you want to build BusyBox with a Cross Compiler? (i386-linux-gcc) Cross Compiler prefix

这个指明交叉编译器名称(其实在编译时的命令行已指定过了……)

C、安装选项下的(${PRJROOT}/rootfs) BusyBox installation prefix,这个指明了编译好后的工具的安装目录。

D、静态编译好还是动态编译好?即是否选择

[ ] Build BusyBox as a static binary (no shared libs)

动态编译的最大好处是节省了宝贵空间,一般来说都是用动态编译,不过我以前动态编译出过问题(其实是库的问题,不关busybox的事),出于惯性,我选择了静态编译,为此多付出了107KB的空间。

E、其它命令,根据需要,自行权衡。

 

 

6、系统初始化文件

内核启动时,最后一个初始化动作就是启动init程序,当然,大多数发行套件的 Linux都使用了与 System V init相仿的init,可以在网上下载System V init套件,下载下来交叉编译。另外,我也找到一篇写得非常不错的讲解如何编写初始化文件的文件,bsd-init,回头附在后面。不过,对于嵌入式系统来讲,BusyBox init可能更为合适,在第6步中选择命令的时候,应该把init编译进去。

#cd ${PRJROOT}/rootfs/etc

#vi inittab

我的inittal文件如下:

#指定初始化文件

::sysinit:/etc/init.d/rcS

#打开一个串口,波特率为9600

::respawn:/sbin/getty 9600 ttyS0

#启动时执行的shell

::respawn:/bin/sh

#重启时动作

::restart:/sbin/init

#关机时动作,卸载所有文件系统

::shutdown:/bin/umount -a –r

 

保存退出;

 

再来编写rcS脚本:

#mkdir ${PRJROOT}/rootfs/etc/init.d

#cd ${PRJROOT}/rootfs/etc/init.d

#vi rcS

我的脚本如下:

#!/bin/sh

 

#Set Path

PATH=/sbin:/bin

export PATH

 

syslogd -m 60

klogd

 

#install /proc

mount -n -t proc none /proc

 

#reinstall root file system by read/write mode(need: /etc/fstab)

mount -n -o remount,rw /

 

#reinstall /proc

mount -n -o remount,rw -t proc none /proc

 

#set lo ip address

ifconfig lo 127.0.0.1

 

#set eth0 ip address

#当然,这样子做只是权宜之计,最后做的应该是在这一步引导网络启动脚本,像RedHat

#那样,自动读取所有指定的配置文件来启动

ifconfig eth0 192.168.0.68 netmask 255.255.255.0

 

#set route

#同样的,最终这里应该是运行启动路由的脚本,读取路由配置文件

route add default gw 192.168.0.1

 

#还差一个运行服务程序的脚本,哪位有现成的么?

#网卡/路由/服务这三步,事实上可以合在一步,在rcS这一步中,做一个循环,运行指定启动目录下的所有脚,先将就着这么做吧,确保系统能够正常启动了,再来写这个脚本。

 

#set hostname

hostname MyLinux

 

保存退出。

 

编写fstab文件

#vi fstab

我的fstab很简单:

/dev/hda1 / ext2 defaults 1 1

none /proc proc defaults 0 0

 

第五章 让MyLinux能够启动

前一章,我们把编译好的内核、应用程序、配置文件都拷贝至rootfs目录对应的子目录中去了,这一步,就是把这些文件移植至目标机的存储器。这里,我是先另外拿一块硬盘,挂在我的开发机上做的测试,因为我的本本用来写文档,PC机用来做开发机,已经没有另外的机器了……但是本章只是讲述一个一般性的过程,并不影响你直接在目标主机上的工作。

因为以后目标机识别硬盘序号都是hda,而我现在直接挂上去,则会是hdb、hdc……这样,安装lilo时有点麻烦(虽然也可以实现)。所以我想了另一个办法:

 把新硬盘挂在IDE0的primary上,进入linux后,会被认为是had;

 原来主机的装Redhat的硬盘,我将它从IDE0的primary上变到了IDE1 的primary,因为它的lilo早已装好,基本上不影响系统的使用;

 

分区和格式化

BIOS中改为从第二个硬盘启动;也就是从我原来开发机启动,新的硬盘被识别成了had。

#fdisk /dev/hda

用d参数删除已存在的所有分区

用n参数新建一个分区,也是就/dev/hda1

格式化

#mkfs.ext2 /dev/hda1

 

安装bootloader

因为我是X86平台,所以直接用了lilo,如果你是其这平台,当然,有许多优秀的bootloader供你选择,你只需查看其相应的说明就可以了。

编译lilo配置文件,我的配置文件名为target.lilo.conf,置于${PRJROOT}/rootfs/etc目录。内容如下所示:

boot=/dev/hda

disk=/dev/hda

bios=0x80

image=/boot/bzImage-2.4.18-rmk5

label=Linux

root=/dev/hda1

append="root=/dev/hda1"

read-only

 

//新建文件夹,为mount做新准备

#mkdir /mnt/cf

//把目标硬盘mount上来

#mount –t ext2 /dev/hdc1 /mnt/cf

回到rootfs

#cd ${PRJROOT}/rootfs

拷贝所有文件至目标硬盘

#cp –r * /mnt/cf

 

这样,我们所有的文件都被安装至目标硬盘了,当然,它还不能引导,因为没有bootloader。使用如下命令:

# lilo -r /mnt/cf -C etc/target.lilo.conf

Warning: LBA32 addressing assumed

Added Linux *

-r :改变根目标为/mnt/cf ,这样配置文件其实就是/mnt/cf/etc/target.lilo.conf,也就是我们先前建立的文件。

当然,完成这一步,需要lilo22.3及以后版本,如果你的版本太旧,比如Redhat9.0自带的,就会出现下面的信息:

#lilo –r /mnt/cf –C etc/target.lilo.conf

Fatal: open /boot/boot.b: No such file or directory

这时,你需要升级你的lilo,或者重新安装一个。

 

启动系统

#umount /mnt/cf

#reboot

 

将BIOS改为从IDE0启动,也就是目标硬盘。如果一切顺利,你将顺利进入一个属于你的系统。

 

回头再来看看我们的工作空间吧

[root@skynet lib]# df /dev/hda1

Filesystem 1K-blocks Used Available Use% Mounted on

/dev/hda1 3953036 1628 3750600 1% /mnt/cf

 

总共花去了我1628KB的空间,看来是没有办法放到软盘里边去了^o^,不过一味求小,并不是我的目标。

 

[root@skynet skynet]# ls ${PRJROOT}

bootloader build-tools debug doc images kernel rootfs sysapps tmp tools

这几个目录中的文件,呵呵,与本文一开头规划的一样

 

[root@skynet skynet]# ls build-tools/

buildroot buildroot-0.9.27.tar.tar

包含了buildroot源码及压缩包,事实上buildroot下边还包括了GNU其它工具的源码、编译文件等诸多内容,是我们最重要的一个文件夹,不过到现在它已经没有多大用处了,如果你喜欢,可以将它删除掉(不建议)。

 

[root@skynet skynet]# ls images

2.4.18-rmk5 bzImage-2.4.18-rmk5 System-2.4.18-rmk5 vmlinux-2.4.18-rmk5

内核映像及配置文件等,如果你有模块,因为还有相应的目录

 

[root@skynet skynet]# ls kernel/

linux-2.4.27 linux-2.4.27.tar.bz2

内核源码及压缩包

 

[root@skynet skynet]# ls rootfs/

bin boot dev etc home lib linuxrc proc root sbin tmp usr var

制作好的根文件系统,重中之重,注意备份……

 

[root@skynet skynet]# ls sysapps/

busybox-1.00 busybox-1.00.tar.gz

busybox-1.00源码包,或许你还要继续添加/删除一些命令……

 

[root@skynet skynet]# ls tools

bin i386-linux i386-linux-uclibc include info lib man

这个也很重要,我们制作好的交叉开发工具链。如果你要继续开发程序,这个目录重要性就很高了。

 

其它目录暂时是空的。

 

 

第六章 完善MyLinux

关于进一步的调试,你可以在开发机上使用chroot /mnt/cf /bin/sh这样的命令,以使我们在目标根文件系统上工作。

 

支持多用户

因为我在编译busybox时,已经将它的多用户那一大堆命令编译了进来。现在关键是的要为其建立相应的文件;

进入原来的开发机,进入rootfs目录,切换根目录

#chroot rootfs/ /bin/sh

A、 建立/etc/passwd文件,我的文件内容如下:

root:x:0:0:root:/root:/bin/bash

B、 建立/etc/group文件,我的文件内容如下:

root:x:0:

bin:x:1:

sys:x:2:

kmem:x:3:

tty:x:4:

tape:x:5:

daemon:x:6:

disk:x:7:

C、 为root建立密码

#passwd root

 

试试用addgroup/addusr……这堆命令。然后重启,从目标硬盘上启动;从console口,9600登陆试试(因为我在inittab中启用了ttyS0,我未来的目标机,是没有显卡的,需要从console口或SSH进去管理)

MyLinux login: root

Password:

 

BusyBox v1.00 (2004.10.10-04:43+0000) Built-in shell (ash)

Enter 'help' for a list of built-in commands.

 

~ #

成功了……

 

增加WEB Server

Busybox里边有httpd选项,不过我编译时并没有选择,所以还是自己来安装。我使用的软件是thttpd-2.25b.tar.gz,将它移至sysapps目录下。

[root@skynet sysapps]# tar zxvf thttpd-2.25b.tar.gz

[root@skynet sysapps]# cd thttpd-2.25b

//配置

[root@skynet thttpd-2.25b]# CC=i386-linux-gcc ./configure --host=$TARGET

……

i386-linux-gcc -static htpasswd.o -o htpasswd -lcrypt

make[1]: warning: Clock skew detected. Your build may be incomplete.

make[1]: Leaving directory `/home/skynet/sysapps/thttpd-2.25b/extras'

//拷贝至根文件目录

[root@skynet thttpd-2.25b]# cp thttpd ${PRJROOT}/rootfs/usr/sbin

//trip处理

[root@skynet thttpd-2.25b]# i386-linux-strip ${PRJROOT}/rootfs/usr/sbin/thttpd

 

剩下的,就发挥各人的想像吧……

 

 

独孤九贱 2005-11-1 02:34

 

继续补完

 

不好意思,最近工作太忙,好久没有来搞这个东东了,加之心爱的手机丢了,心情又不太好,不过一切都过去了,继续来将它补充完整。

 

修改启动脚本

在前面写rcS启动脚本中。当时只是为了系统能够正常地启动,在启动网卡/路由/服务等时,有如下语句:

——————————————————————————————————————————————

#set lo ip address

ifconfig lo 127.0.0.1

 

#set eth0 ip address

#当然,这样子做只是权宜之计,最后做的应该是在这一步引导网络启动脚本,像RedHat

#那样,自动读取所有指定的配置文件来启动

ifconfig eth0 192.168.0.68 netmask 255.255.255.0

 

#set route

#同样的,最终这里应该是运行启动路由的脚本,读取路由配置文件

route add default gw 192.168.0.1

……

———————————————————————————————————————————————

这样配置的最大坏处就是不能根据配置文件自定义,每次开机都定死了,现在来修改它,将这段语句删除之,换成如下语句:

for i in /etc/start/S??* ;do

# Ignore dangling symlinks (if any).

[ ! -f "$i" ] && continue

 

echo "Running $i ."

case "$i" in

*.sh)

# Source shell script for speed.

(

trap - INT QUIT TSTP

set start

. $i

)

;;

*)

# No sh extension, so fork subprocess.

$i start

;;

esac

echo "Done $i ."

echo

done

解释一下,这段语句的作用,就是启动/etc/start/目录下,所有以S开头的脚本文件,可以启动两类,以sh结尾或没有 sh后缀的。

这样,我们在/etc/目录下再新建一目录start/,这里面就是我们启动时需要的脚本的。先来启动网卡。

 

修改网卡配置文件

我是根据Red hat的作法,把网卡配置放在/etc/sysconfig/network-scripts目录下,类似于ifcfg-ethXX这样子,它们的语法是:

DEVICE=eth0

BOOTPROTO=static

BROADCAST=88.88.88.255

IPADDR=88.88.88.44

NETMASK=255.255.255.0

NETWORK=88.88.88.0

ONBOOT=yes

好,建立这些目录和文件,我共有两个文件ifcfg-ethXX。回到/etc/start目录,建立网卡的启动脚本S01interface:

#!/bin/sh

 

. /etc/sysconfig/network

#enable ip_forword

echo >1 /proc/sys/net/ipv4/ip_forward

 

#enable syn_cookie

echo >1 /proc/sys/net/ipv4/tcp_syncookies

 

#enable loopback interface

/sbin/ifconfig lo 127.0.0.1

 

#eanble ethernet interface

/usr/sbin/bootife

 

#set hostname

if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]

then

HOSTNAME=localhost

fi

 

/bin/hostname ${HOSTNAME}

 

请注意这个脚本文件,有两个地方:

1、包含了另一个配置文件/etc/sysconfig/network,在这里,我也是照抄了redhat,我的/etc/sysconfig/network这个文件的内容如下:

NETWORKING=yes

HOSTNAME=skynet

GATEWAY=88.88.88.2

2、在启动网卡时,我使用了

#eanble ethernet interface

/usr/sbin/bootife

bootife 是我自己写的一个C程序,作用是读取/etc/sysconfig/network-scripts/下面的ifcfg-ethXX文件,并配置之,本来这里就该用shell来完成更合适一点,无奈,偶shell功底实在差了一点(刚学几天),就是想从Redhat中照抄过来,反复试了几次也没有成功。所以被逼无奈用C来完成之,后面我会附上我的C的源码,也希望哪位大哥能够写一段Shell的程序代替它,放上来大家共享之。

 

修改路由启动文件

同样的,我在/etc/start下,建立新脚本S02route.sh,它的作用是启动所有配置的静态路由:

#!/bin/bash

 

. /etc/sysconfig/network

# Add non interface-specific static-routes.

 

if [ -f /etc/sysconfig/static-routes ]

then

grep "eth*" /etc/sysconfig/static-routes | while read ignore args ; do

# echo "/sbin/route add -"$args

/sbin/route add -$args

done

fi

 

#Add defalut gw

/sbin/route add default gw ${GATEWAY}

 

OK,启动时读取的配置文件是/etc/sysconfig/static-routes ,它的语法和Redhat是一样的,请参照建立此文件。

 

启动服务程序

新建启动脚本S03server:

#!/bin/sh

#------------------------------------------------------------------

#-- Source

#-- Author(s) : kendo

#-- Email: [email]kendo999@sohu.com[/email]

#-- http://www.skynet.org.cn

#-- 2005/10/31

#------------------------------------------------------------------

 

. /etc/sysconfig/bootserver

 

if [ "$enable_httpd" = 1 ] ; then

. /etc/scripts/httpd.sh $1

fi

 

if [ "$enable_adsl" = 1 ] ; then

……

fi

 

if [ "$enable_udhcpd" = 1 ] ; then

……

fi

 

很简单,根据相应变量的值,调用相应的脚本。

最新评论共有 4 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册