首页 > 代码库 > 制作linux根文件系统
制作linux根文件系统
转载地址:http://wenku.baidu.com/view/2cb1b4707fd5360cba1adb14.html
-
转
嵌入式根文件系统制作
转自:http://wenku.baidu.com/view/2cb1b4707fd5360cba1adb14.html
根文件系统制作
注:busybox下载地址:http://www.busybox.net/
目标:用busybox定制一个很小的文件系统,并且运行用户编译的hello。
一、文件系统介绍
二、构建根文件系统
根文件系统制作
注:busybox下载地址:http://www.busybox.net/
目标:用busybox定制一个很小的文件系统,并且运行用户编译的hello。
一、文件系统介绍
二、BusyBox介绍
三、实验步骤
四、分析inittab文件
五、文件系统启动过程
六、附录:linux目录结构
一、文件系统介绍
文件系统:是操作系统用于明确磁盘或分区上的文件的方法和数据结构,即在磁盘上组织文件的方法。Linux文件系统是一个完整的统一体,组织到一个树形目录结构中。
Linux遵守文件系统科学分类标准(FHS),一个定义许多文件和目录的名字和位置的标准。
w 主要规则如下:
l 配置文件放在/etc目录下
l 设备文件放在/dev目录下
l 库文件放在目录/lib目录下
l 存放系统编译后的可执行文件、命令的目录是/bin、/sbin、/usr/bin、/usr/sbin目录
在嵌入式系统中,根目录下的很多目录都可以删除,如下:
l 为多用户提供可扩展环境的所有目录都应该删除;如(/home,/mnt,/root)
l 根据引导加载情况,/boot目录可以删除。
其余的目录
l /bin,/dev,/etc,/proc,/sbin,/usr,/lib都是不可缺少的。
二、构建根文件系统
Linux的根文件系统包括支持linux系统正常运行的基本内容,至少应包括以下几项内容:
l 基本的文件系统结构,如bin、dev、etc、sbin,lib、usr、proc。
l 基本程序运行所需的动态库。
l 基本的系统配置文件。(自己编写)
l 必要的设备文件支持。
l 基本的应用程序,如sh、ls、cp等。
构建根文件系统就是往相应的目录添加相应的文件。如:
l 在/dev添加设备文件,
l 在/etc添加配置文件,(创建)
l 在/bin添加命令或者程序,(选择)
l 在/lib添加动态库等。(复制)
添加设备文件
Linux对所有外部设备的访问都是以文件的形式来进行;
在Linux系统中,可以找到设备对应的文件,称为设备文件;
设备文件(也叫做设备节点)都存放在/dev的目录下
w 在/dev目录下,建立设备文件的命令是mknod;
如:mknod /dev/led c 231 0 (系统分配好的)
上面例子中 “/dev/led”是设备文件路径;“c”是指定为字符设备;“231”是主设备号;“0”是次设备号。
w Linux系统是靠主、次设备号来联系驱动程序和设备文件的;
三、BusyBox介绍
Busybox 提供的程序包括:
l 具有shell功能,如csh
l 提供一个迷你的vi编辑器
l 提供系统不可或缺的/sbin/init程序
l 其他的系统基本命令,如:ls,mkdir,ifconfig等。
四、实验步骤
1、 建立工作目录(这里建议统一用这个路径,否则在指定安装路径及copy库文件的路径都要改)
设定工作目录为/root/build_rootfs/, 下载busybox到该目录
Mkdir /root/build_rootfs
2、 建立根目录, 该目录就是我们要移植到目标板上的目录,对于嵌入式的文件系统,根目录下必要的目录包括bin,dev,etc,usr,lib,sbin,proc。
cd /root/build_rootfs
mkdir rootfs
cd rootfs
mkdir bin dev etc usr lib sbin proc
mkdir usr/bin usr/sbin usr/lib
(解析各目录的作用)
/bin bin是Binary的缩写。这个目录存放着最经常使用的命令。
/sbin s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。
/dev dev是Device(设备)的缩写。该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
/etc这个目录用来存放所有的系统管理所需要的配置文件和子目录。
/usr 我们要用到的很多应用程序和文件几乎都存放在usr目录下
/usr/bin存放着许多应用程序;
/usr/sbin存放root超级用户使用的管理程序;
/usr/lib存放一些常用的动态链接共享库和静态档案库;
/lib这个目录里存放着系统最基本的动态链接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。
/proc这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里.
3、 交叉编译busybox
我们在配置busybox的时候是基于默认配置之上来配置的;先make defconfig就是把busybox配置成默认,然后再make menuconfig来配置busybox。
说明:我们在配置一个源代码包之前,可以先阅读源码包目录下的README和INSTALL文件以及Makefile的注释部分,也可以到http://www.busybox.net网站以获取帮助。
http://www.busybox.net/FAQ.html#configure的第二个问题2 How do I configure busybox?有介绍怎么去配置。
(1)、在/root/build_rootfs解压
tar -jxvf busybox-1.5.0.tar.bz2
mv busybox-1.5.0 busybox (更名,不是必须的)
cd busybox
(2)、添加交叉工具链
export PATH=/usr/local/arm/3.3.2/bin:$PATH
(3)、配置编译
make defconfig
make menuconfig
配置时,我们基于默认配置,再配置它为静态编译,安装时不要/usr路径,把Miscellaneous Utilities 下的“taskset”选项去掉,不然会出错。
如下:
Busybox setting
->builds options
->[*] build busybox as a static binary(a)
->installitation options
->[*] don’t use /usr (b)
Miscellaneous Utilities ―> (c)
[ ] taskset
其他选项都是一些linux基本命令选项,自己需要哪些命令就编译进去,一般用默认的就可以了。保存退出。
(a)这个选项是一定要选择的,这样才能把busybox编译成静态链接的可执行文件,运行时才独立于其他函数库.否则必需要其他库文件才能运行,在单一个linux内核不能使他正常工作。
(b)这个选项也一定要选,否则make install后,busybox将安装在原系统的/usr下,这将覆盖掉系统原有的命令.选择这个选项后,make install后会在busybox目录下生成一个叫_install的目录,里面有busybox和指向他的链接.
4、编译安装
make ARCH=arm CROSS_COMPILE=arm-linux- CONFIG_PREFIX=/root/build_rootfs/rootfs all install
(此时bin(195个 290M) sbin(58个 86.4M) 已安装了文件,其实是busybox的可执行文件和指向它的链接。不同的链接名完成不同的功能,命令行调用作为一个参数传给busybox,即可完成相应的功能)
ARCH指定平台
CROSS_COMPILE指定交叉编译
CONFIG_PRRFIX指定安装的路径
由于/root/build_rootfs/rootfs/linuxrc 和/root/build_rootfs/rootfs/sbin/init 是同一个程序,可以把linuxrc删除,以节省空间。
此时U-BOOT启动参数应该设为:(板上uboot启动时再执行)
Setenv bootargs root=/dev/mtdblock2 init=/sbin/init console=ttySAC0,115200 display=sam320 men=64M devfs=mount
如果不rm linuxrc,则 init=/linuxrc
也可以先rm linuxrc,再手写脚本 linuxrc。通过linuxrc中执行“exec /sbin/init”来执行sbin/init。
5、 copy C库
交叉应用程序的开发需要用到交叉编译的链接库,交叉编译的链接库是在交叉工具链的lib目录下;我们在移植应用程序到我们的目标板的时候,需要把交叉编译的链接库也一起移植到目标板上,这里我们用到的交叉工具链的路径是/usr/local/arm/3.3.2/,所以链接库的目录是/usr/local/arm/3.3.2/lib(本来跟目标板相关的目录是/usr/local/arm/3.3.2/arm-linux, 因此要拷贝的链接库应该在/usr/local/arm/3.3.2/arm-linux/lib下,但是此目录的很多链接都是链接到/usr/local/arm/3.3.2/lib目录下的库文件,所以我们从/usr/local/arm/3.3.2/lib目录拷贝库),此目录下有四种类型的文件(其实就2种:.so动态库 .a静态库):
(1) .so动态库(了解)
A、实际的共享链接库(libname-version.so)
如:libc-2.3.2.so
B、主修订版本的符号链接. (lib.so.version)
程序一旦链接了特定的链接库,它将会使用其符号链接,程序启动时,加载器在加载程序之前,会加载该文件。
如:libc.so.6
C、与版本无关的符号链接(libname.so)
这些符号链接的只要功能是为需要链接特定的链接库的所有程序提供一个通用的条目,与版本号无关。
如:libc.so
(2) .a静态库
静态链接库包文件
如:libc.a
(1)、进入链接库目录
cd /usr/local/arm/3.3.2/lib
编写一个shell文件,用于copy实际的共享链接库;主修订版本的符号链接;动态连接器及其符号链接到目标板根目录下的lib。
w 主要的动态链接库:
ld 动态链接器
libc 主C链接库
libcrypt 秘密学链接库
libdl 用来动态加载共享文件的动态库
libm 数学库
libpthread多线程库
还可以通过arm-linux-readelf命令来找出应用程序依赖于哪些动态链接库;
如:arm-linux-readelf -d hello; //hello只是打印一句“hello”的程序;
(2)、vi cp.sh
内容如下:
(仅供参考,可以自己写)
for file in libc libcrypt libdl libm libnss_dns libnss_files libpthread libresolv libutil
do
cp $file-*.so /root/build_rootfs/rootfs/lib (1)
cp -d $file.so.[*0-9] /root/build_rootfs/rootfs/lib (2)
done
cp -d ld*.so* /root/build_rootfs/rootfs/lib (3)
cp -d libgcc_s*.so* /root/build_rootfs/rootfs/lib /*标准C库*/
cp -d libstdc++.so* /root/build_rootfs/rootfs/lib
cp -d libuuid.so* /root/build_rootfs/rootfs/usr/lib
cp -d libz.so* /root/build_rootfs/rootfs/usr/lib
cp -d libpng*.so* /root/build_rootfs/rootfs/usr/lib
cp -d libjpeg.so* /root/build_rootfs/rootfs/usr/lib /*解码库*/
(-d 保持原来的链接属性)
(3)、保存退出
(1)第一个cp命令会复制实际的共享库
(2)第二个cp命令会复制符号链接本身
(3)第三个cp命令会复制动态连接器及其符合链接
(4)、执行刚编写的shell。
source cp.sh
( lib(20个 61.9M) usr/lib(9个 639K) 安装了文件)
这样就把链接库复制过来了。
(5)、接着我们还要缩小复制过来的链接库的体积,如下:
arm-linux-strip –s /root/build_rootfs/rootfs/lib/lib* (根据具体情况修改)
(lib由61.9M 变为5.64M)
6、 建立配置文件
这里我们没有添加inittab(执行顺序)等文件,我们只是添加了一个c shell初始化时读取的文件。
内核启动的最后,会执行sbin/init程序,init程序在启动的最后会执行/bin/sh,sh在启动的时候会读取文件。
我们在/etc/profile文件里设定PATH,LD_RARYLIB_PATH环境变量,目的是配置用户程序运行的环境。
cd /root/build_rootfs/rootfs/etc
vi profile
内容如下
#!/bin/sh
echo "Set seaech library in /etc/profile"
export LD_LIBRARY_PATH=/lib //定义查找可用共享对象的位置 //usr/lib
echo "Set user path in /etc/profile"
export PATH=/bin:/sbin:/usr/bin //命令的路径
保存退出
7、 添加一个用户程序
进入工作目录
cd /root/build_rootfs/
编辑源文件
vi hello.c
内容如下
#include <stdio.h>
main()
{
printf(“welcome to my rootfs\n”);
}
保存退出
交叉编译
arm-linux-gcc hello.c –o hello(下载到目标板的话必须交叉编译)
复制到目标板的根目录
mv hello /root/build_rootfs/rootfs/usr/bin
8、 制作cramfs映像
找到mkcramfs工具(该工具只能制作可读的镜像文件,而mkfs.jffs2工具或以把文件系统制作成可读可写的镜像文件),把它复制到“/root/build_rootfs”目录下。
cd /root/build_rootfs/
./mkcramfs rootfs rootfs.cramfs
rootfs.cramfs就是我们要烧写到目标板的映像文件
9、烧写rootfs.cramfs到3分区,启动开发板,运行hello程序。
将rootfs.cramfs文件拷贝到tftp下载的目录下,如拷贝到linux 系统中的/tftpboot目录;
开发板的u-boot通过tftp命令下载;
根据分区表来烧写;
10、U-BOOT下载和烧写:
烧写内核
tftp 30008000 zImage
nand erase 0x40000 0x1c0000
nand write 30008000 0x40000 0x1c0000
烧写根文件系统
tftp 30008000 rootfs.cramfs
nand erase 0x200000 0x1e00000
nand write 30008000 0x200000 0x1e00000
11、启动:
setenv bootargs root=/dev/mtdblock2 init=/sbin/init console=ttySAC0,115200 display=sam320 men=64M devfs=mount
setenv bootcmd nand read 0x30008000 0x40000 0x1c0000 \;go 0x30008000
saveenv
reset
等待5秒钟,自动运行linux系统。
12、通过NFS挂载:
setenv bootargs root=/dev/nfs nfsroot=192.168.11.58:/home/gec2440 ip=192.168.11.56 init=/sbin/init console=ttySAC0,115200 display=sam320
另,还得开通NFS服务和设置要挂载的目录共享(系统-管理-服务器设置-NFS,在用户“user access”卡中勾选第一项)
五、分析inittab文件4
Inittab文件中每一行的格式如下:
id:runlevel:action:process
其中:
l Id:用来指定所启动进程的控制台,在嵌入式系统中一般不添加;
l Runlevel:运行级别;
l Action:指出init程序在执行相应process时,对process所采取的动作
l Process:具体的执行程序;
inittab文件的action字段中,有以下八个应用到process的动作:
l Sysinit: 为init提供初始化命令行的路径;
l Respawn: 当该进程死亡时,init将重新启动该进程,不等待该 进程的结束;
l Askfirst: 当相应的进程终止便重新启动,会在控制台显示 “Please press Enter to activate this console.”的信息。
l Wait: 启动进程并等待其结束;
l Once: 启动相应的进程,但不等待该进程结束;
l Ctrlaltdel: 当按下Ctrl-Alt-Delete组合键时,执行相应的进程;
l Shutdown: 当系统关机时,执行相应的进程;
l Restart: init从新启动时,执行相应的进程。
六、文件系统启动过程
-----------------简单的rootfs的启动过程:
init=/linuxrc是二进制文件 ,而linuxrc是/sbin/init 的链接文件,它会去读取配置文件/rootfs/etc/profile或者inittab ,然后进入shell控制台。
------ 以gec2440文件系统做讲解 su 2009 -03 -09 ------------
1 init=/linuxrc 根目录的,
2 exec /sbin/init init 是个2进制文件,init程序需要读取配置文件/etc/inittab
3 inittab是一个不可执行的文本文件,它有若干行指令所组成。
/etc/inittab 文件中:
# This is run first except when booting
::sysinit:/etc/init.d/rcS //启动时自动执行/etc/rc.d/rc.sysinit脚本 4
# Start an "askfirst" shell on the console
#::askfirst:-/bin/bash
::askfirst:/bin/bash //类似于respawn,主要用途是减少系统上执行的终端应用程序的数量,会在控制台上显示“please press enter to active this console”,等待用户按下”Enter ”键。
# Stuff to do when restarting the init process
::restart:/sbin/init //重启时执行
#::once:/sbin/raja.sh
::once:/usr/etc/rc.local //启动相应的进程,但不等待该进程结束 5
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot //在启动过程中允许按CTRL-ALT-DELETE重启系统
::shutdown:/bin/umount -a –r //重启时执行
4 /etc/init.d/rcS 完成一些系统初始化的工作 ,主要完成的工作有:激活交换分区,检查磁盘,加载硬件模块以及其它一些需要优先执行任务。
其 中:
/bin/mount –a 实际上是把 /etc/fstab 中的设备 mount 过去。
(-a Mount all filesystems (of the given types) mentioned in fstab.)
5 接着执行 /usr/etc/rc.local
这里执行一些初试初始化脚本,配置IP等,创建目录。
最后执行根目录的 testshell
6 在testshell 里执行 /project/PMP/src/pmp 即我们的应用程序。
cd /project/PMP/src
exec ./pmp -qws
七、附录:linux目录结构
/bin bin是Binary的缩写。这个目录存放着最经常使用的命令。
/boot这里存放的是启动Linux时使用的一些核心文件,包括一些链接文件以及镜像文件。(BIOS自检->MBR(GRUB)->KERNEL->KERNEL自解压->内核初始化->内核启动)/dev dev是Device(设备)的缩写。该目录下存放的是Linux的外部设备,在Linux中访问设备的方式和访问文件的方式是相同的。
/etc这个目录用来存放所有的系统管理所需要的配置文件和子目录。
/home用户的主目录,在Linux中,每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。
/lib这个目录里存放着系统最基本的动态链接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。
/lost+found这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。
/mnt在这里面中有四个目录,系统提供这些目录是为了让用户临时挂载别的文件系统的,我们可以将光驱挂载在/mnt/cdrom上,然后进入该目录就可以查看光驱里的内容了。
/proc这个目录是一个虚拟的目录,它是系统内存的映射,我们可以通过直接访问这个目录来获取系统信息。这个目录的内容不在硬盘上而是在内存里,我们也可以直接修改里面的某些文件,比如可以通过下面的命令来屏蔽主机的ping命令,使别人无法ping你的机器:
echo 1 > /proc/sys/net/ipv4/icmp_echo_
ignore_all。
/root该目录为系统管理员,也称作超级权限者的用户主目录。
/sbin s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序。
/tmp这个目录是用来存放一些临时文件的。
/usr 我们要用到的很多应用程序和文件几乎都存放在usr目录下。具体来说:
/usr/X11R6存放X-Windows的目录;
/usr/games存放着XteamLinux自带的小游戏;
/usr/bin存放着许多应用程序;
/usr/sbin存放root超级用户使用的管理程序;
/usr/doc Linux技术文档;
/usr/include用来存放Linux下开发和编译应用程序所需要的头文件;
/usr/lib存放一些常用的动态链接共享库和静态档案库;
/usr/local这是提供给一般用户的/usr目录,在这里安装一般的应用软件;
/usr/man帮助文档所在的目录;
/usr/src Linux开放的源代码,就存在这个目录,爱好者们别放过哦;
/var这个目录中存放着在不断扩充着的东西,我们习惯将那些经常被修改的目录放在这个目录下。包括各种日志文件。如果你想做一个网站,你也会用到/var/www这个目录。
制作linux根文件系统