第11课第1节 构建根文件系统之启动第1个程序
1、uboot:启动内核
2、内核:启动应用程序:首先要挂接根文件系统,然后再启动应用程序
3、构建根文件系统
内核怎样启动第一个应用程序
1、"/dev/console"对应的是终端设备
sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) //代表标准输入
(void) sys_dup(0); //代表标准输出
(void) sys_dup(0); //代表标准错误
2、run_init_process来启动命令行传入的"init=xxxx"或者"/sbin/init"。但是如果"/sbin/init"执行不成功,就往下执行"/etc/init"、"/bin/init"、"/bin/sh"
当我们启动内核用ps查看:
# ps
PID Uid VSZ Stat Command
1 0 3092 S init
771 0 3096 S -sh
第11课第2节 构建根文件系统之init进程分析
启动开发板后用命令查看一下:
# ls
bin lib mnt root tmp
dev linuxrc opt sbin usr
etc lost+found proc sys
引出busybox:命令都是到busybox的链接
# ls -l /bin/ls
lrwxrwxrwx 1 0 0 7 Dec 24 2010 /bin/ls -> busybox
# ls -l /bin/cp
lrwxrwxrwx 1 0 0 7 Dec 24 2010 /bin/cp -> busybox
# ls
bin lib mnt root tmp
dev linuxrc opt sbin usr
etc lost+found proc sys
# busybox ls
bin lib mnt root tmp
dev linuxrc opt sbin usr
etc lost+found proc sys
我们可以发现我们的init进程也是到busybox的链接,所以我们要分析init进程就需要找busybox的源码来分析
# ls /sbin/init
/sbin/init
# ls /sbin/init -l
lrwxrwxrwx 1 0 0 14 Dec 24 2010 /sbin/init -> ../bin/busybox
回顾一下:
uboot的目的是启动内核
内核的目的是启动应用程序:先启动第一个进程init进程
最终目的是启动客户的程序
由于我们客户应用程序的不同,所以我们的init程序有如下几步:
1、读取配置文件
2、解析配置文件
3、执行用户程序
busybox->init_main
parse_inittab
file = fopen(INITTAB, "r");//打开配置文件"/etc/inittab"
new_init_action //①创建一个init_action结构,填充
//②把这个结构放入init_action_list链表
run_actions(SYSINIT);
waitfor(a, 0); //执行应用程序,等待它执行完毕
run(a); //创建process子进程
waitpid(runpid, &status, 0); //等待它结束
delete_init_action(a); //在init_action_list链表里删掉
run_actions(WAIT);
waitfor(a, 0); //执行应用程序,等待它执行完毕
run(a); //创建process子进程
waitpid(runpid, &status, 0); //等待它结束
delete_init_action(a); //在init_action_list链表里删掉
run_actions(ONCE);
run(a); //创建process子进程
delete_init_action(a); //在init_action_list链表里删掉
while (1) {
run_actions(RESPAWN);
if (a->pid == 0) {
a->pid = run(a);
}
run_actions(ASKFIRST);
if (a->pid == 0) {
a->pid = run(a);
打印:"\nPlease press Enter to activate this console. "
等待回车
创建子进程
}
wpid = wait(NULL);//等待子进程退出
while (wpid > 0) {
a->pid = 0; //退出后,就设置pid=0
}
}
/dev/console /dev/null
/etc/inittab
配置文件里指定的应用程序
库
init本身,即busybox
最小根文件系统:
①/dev/console /dev/null
②init本身,即busybox
③/etc/inittab
④配置文件里指定的应用程序
⑤c库
从默认的new_init_action反推出默认的配置文件:
#inittab格式:
#<id>:<runlevels>:<action>:<process>
#runlevels:忽略
#action :执行时机
# <action>: Valid actions include: sysinit, respawn, askfirst, wait, once,
# restart, ctrlaltdel, and shutdown.
#process :应用程序或脚本
::CTRLALTDEL:reboot
::SHUTDOWN:umount -a -r
::RESTART:init
tty2::askfirst:-/bin/sh
tty3::askfirst:-/bin/sh
tty4::askfirst:-/bin/sh
::sysinit:/etc/init.d/rcS
/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "reboot", "");
/* Umount all filesystems on halt/reboot */
new_init_action(SHUTDOWN, "umount -a -r", "");
/* Swapoff on halt/reboot */
if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", "");
/* Prepare to restart init when a HUP is received */
new_init_action(RESTART, "init", "");
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, "");
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
/* sysinit */
new_init_action(SYSINIT, INIT_SCRIPT, "");
new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");
static void new_init_action(int action, const char *command, const char *cons)
1、创建一个init_action结构,填充
2、把这个结构放入init_action_list链表
在busybox目录下面搜索inittab,打开一个inittab文件例子
inittab格式:
<id>:<runlevels>:<action>:<process>
runlevels:忽略
action :执行时机
process :应用程序或脚本
id => /dev/id,用作终端:stdin,stdout,stderr:printf,scanf,err
猜测:既然我们配置文件的目的是启动不同的用户程序,那么:
配置文件:1、指定应用程序
2、何时执行
int main()
{
printf("hello,world!\n"); //c库
fopen(); //c库
fwrite();
}
第11课第3节 构建根文件系统之busybox.WMV
最小根文件系统:
①/dev/console /dev/null
②init本身,即busybox
③/etc/inittab
④配置文件里指定的应用程序
⑤c库
book@book-desktop:/work/system$ tar xjf busybox-1.7.0.tar.bz2
注意首先要设置交叉编译工具链:改两个地方。
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
查看E:\colin weidongshan\colin_kernel\official\busybox-1.7.0\INSTALL里面教你怎么编译busybox
make menuconfig # This creates a file called ".config"
make # This creates the "busybox" executable
make install # or make CONFIG_PREFIX=/path/from/root install
book@book-desktop:/work/system/busybox-1.7.0$ make menuconfig
book@book-desktop:/work/system/busybox-1.7.0$ make
book@book-desktop:/work/system/busybox-1.7.0$ mkdir -p /work/nfs_root/first_fs
book@book-desktop:/work/system/busybox-1.7.0$ make CONFIG_PREFIX=/work/nfs_root/first_fs install
第11课第4节 构建根文件系统之构建根文件系统.WMV
一:
最小根文件系统:
①/dev/console /dev/null
②init本身,即busybox
③/etc/inittab
④配置文件里指定的应用程序
⑤c库
查看pc机上面的,做上面的①/dev/console /dev/null
book@book-desktop:/work/nfs_root/first_fs$ ls /dev/console /dev/null -l
crw------- 1 root root 5, 1 2013-07-07 07:53 /dev/console
crw-rw-rw- 1 root root 1, 3 2013-07-06 19:18 /dev/null
book@book-desktop:/work/nfs_root/first_fs$ mkdir dev
book@book-desktop:/work/nfs_root/first_fs$ cd dev/
book@book-desktop:/work/nfs_root/first_fs/dev$ sudo mknod console c 5 1
book@book-desktop:/work/nfs_root/first_fs/dev$ sudo mknod null c 1 3
做③/etc/inittab:
book@book-desktop:/work/nfs_root/first_fs/dev$ cd ..
book@book-desktop:/work/nfs_root/first_fs$ ls
bin dev linuxrc sbin usr
book@book-desktop:/work/nfs_root/first_fs$ mkdir etc
book@book-desktop:/work/nfs_root/first_fs$ vi etc/inittab
里面加一句:console::askfirst:-/bin/sh
做⑤c库:
book@book-desktop:/work/nfs_root/first_fs$ mkdir lib
book@book-desktop:/work/nfs_root/first_fs$ cd /work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib
book@book-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$ cp *.so* /work/nfs_root/first_fs/lib -d
book@book-desktop:/work/tools/gcc-3.4.5-glibc-2.3.6/arm-linux/lib$ cd /work/nfs_root/first_fs
book@book-desktop:/work/nfs_root/first_fs$ ls
bin dev etc lib linuxrc sbin usr
最小根文件系统已经做好了
二:制作yaffs映像文件,完善最小根文件系统
1、制作工具
book@book-desktop:/work/nfs_root/first_fs$ cd /work/system/
book@book-desktop:/work/system$ tar xjf yaffs_source_util_larger_small_page_nand.tar.bz2
book@book-desktop:/work/system$ cd Development_util_ok/
book@book-desktop:/work/system/Development_util_ok$ cd yaffs2
book@book-desktop:/work/system/Development_util_ok/yaffs2$ cd utils/
book@book-desktop:/work/system/Development_util_ok/yaffs2/utils$ pwd
/work/system/Development_util_ok/yaffs2/utils
book@book-desktop:/work/system/Development_util_ok/yaffs2/utils$ make
book@book-desktop:/work/system/Development_util_ok/yaffs2/utils$ sudo cp mkyaffs2image /usr/local/bin/
book@book-desktop:/work/system/Development_util_ok/yaffs2/utils$ sudo chmod +x /usr/local/bin/mkyaffs2image
book@book-desktop:/work/system/Development_util_ok/yaffs2/utils$ cd /work/nfs_root/
book@book-desktop:/work/nfs_root$ mkyaffs2image first_fs first_fs.yaffs2
遇到一个问题,不能启动提示:kernel panic - not syncing: No init found. Try passing init= option to kernel.
问题解决:主要原因是编译器的问题,我用的是高版本的编译器,但是库加载的是低版本的编译器。换成低版本的编译器后,改一下环境变量如下
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/tools/gcc-3.4.5-glibc-2.3.6/bin"
至此第一个根文件系统初步已经做好了:启动内核之后,按回车
# cat /etc/inittab
console::askfirst:-/bin/sh
# ls
bin etc linuxrc sbin
dev lib lost+found usr
2、完善最小根文件系统:
当我想用PS命令:
# ps
PID Uid VSZ Stat Command
ps: can't open '/proc': No such file or directory
即使我们创建了proc目录还是不行如下;
# ps
PID Uid VSZ Stat Command
ps: can't open '/proc': No such file or directory
# mkdir proc
# ps
PID Uid VSZ Stat Command
# mount -t proc none /proc
# ps
PID Uid VSZ Stat Command
1 0 3092 S init
2 0 SW< [kthreadd]
3 0 SWN [ksoftirqd/0]
4 0 SW< [watchdog/0]
5 0 SW< [events/0]
6 0 SW< [khelper]
55 0 SW< [kblockd/0]
56 0 SW< [ksuspend_usbd]
59 0 SW< [khubd]
61 0 SW< [kseriod]
73 0 SW [pdflush]
74 0 SW [pdflush]
75 0 SW< [kswapd0]
76 0 SW< [aio/0]
709 0 SW< [mtdblockd]
744 0 SW< [kmmcd]
762 0 3096 S -sh
777 0 3096 R ps
# cd /proc/
# ls
1 744 diskstats locks sys
2 75 driver meminfo sysrq-trigger
3 76 execdomains misc sysvipc
4 762 fb modules timer_list
5 778 filesystems mounts tty
55 asound fs mtd uptime
56 buddyinfo interrupts net version
59 bus iomem partitions vmstat
6 cmdline ioports scsi yaffs
61 cpu irq self zoneinfo
709 cpuinfo kallsyms slabinfo
73 crypto kmsg stat
74 devices loadavg swaps
# cd 1
# ls -l fd
lrwx------ 1 0 0 64 Jan 1 02:00 0 -> /dev/console
lrwx------ 1 0 0 64 Jan 1 02:00 1 -> /dev/console
lrwx------ 1 0 0 64 Jan 1 02:00 2 -> /dev/console
# pwd
/proc/1
注;proc是我们内核提供的虚拟的文件系统
我们要首先就要把proc放到我们做好的文件系统里面:
book@book-desktop:/work/nfs_root/first_fs$ mkdir proc
book@book-desktop:/work/nfs_root/first_fs$ ls
bin dev etc lib linuxrc proc sbin usr
如果不想手工挂载,要加一个配置文件:
book@book-desktop:/work/nfs_root/first_fs$ vi etc/inittab
console::askfirst:-/bin/sh
::sysinit:/etc/init.d/rcS
那么我们还得创建脚本文件:/etc/init.d/rcS
book@book-desktop:/work/nfs_root/first_fs$ mkdir etc/init.d
book@book-desktop:/work/nfs_root/first_fs$ vi etc/init.d/rcS
mount -t proc none /proc
book@book-desktop:/work/nfs_root/first_fs$ chmod +x etc/init.d/rcS
book@book-desktop:/work/nfs_root/first_fs$ cat etc/init.d/rcS
mount -t proc none /proc
当然我们可以通过etc/init.d/rcS来mount -t proc none /proc挂载根文件系统,我们还有另外一种办法通过mount -a
mount -a 就是读出etc/inittab,根据这个里面的内容来挂载系统.mount -a 命令依赖于文件etc/init.d/rcS
book@book-desktop:/work/nfs_root/first_fs$ vi etc/init.d/rcS
#mount -t proc none /proc
mount -a
book@book-desktop:/work/nfs_root/first_fs$ vi etc/fstab
book@book-desktop:/work/nfs_root/first_fs$ cat etc/fstab
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
book@book-desktop:/work/nfs_root/first_fs$ cat etc/init.d/rcS
#mount -t proc none /proc
mount -a
实验一下:
book@book-desktop:/work/nfs_root/first_fs$ cd ..
book@book-desktop:/work/nfs_root$ mkyaffs2image first_fs first_fs.yaffs2
下载到开发板
# ps
PID Uid VSZ Stat Command
1 0 3092 S init
2 0 SW< [kthreadd]
3 0 SWN [ksoftirqd/0]
4 0 SW< [watchdog/0]
5 0 SW< [events/0]
6 0 SW< [khelper]
55 0 SW< [kblockd/0]
56 0 SW< [ksuspend_usbd]
59 0 SW< [khubd]
61 0 SW< [kseriod]
73 0 SW [pdflush]
74 0 SW [pdflush]
75 0 SW< [kswapd0]
76 0 SW< [aio/0]
709 0 SW< [mtdblockd]
744 0 SW< [kmmcd]
765 0 3096 S -sh
766 0 3096 R ps
# cat /proc/mounts
rootfs / rootfs rw 0 0
/dev/root / yaffs rw 0 0
proc /proc proc rw 0 0
但是
# ls /dev
console null
在这里引入了udev,mdev概念:自动创建挂载设备
在busybox下面的mdev.txt里面有:
Here's a typical code snippet from the init script:
[1] mount -t sysfs sysfs /sys
[2] echo /bin/mdev > /proc/sys/kernel/hotplug
[3] mdev -s
Of course, a more "full" setup would entail executing this before the previous
code snippet:
[4] mount -t tmpfs mdev /dev
[5] mkdir /dev/pts
[6] mount -t devpts devpts /dev/pts
book@book-desktop:/work/nfs_root$ cd first_fs/
book@book-desktop:/work/nfs_root/first_fs$ mkdir sys
book@book-desktop:/work/nfs_root/first_fs$ vi etc/fstab
book@book-desktop:/work/nfs_root/first_fs$ cat etc/fstab
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
book@book-desktop:/work/nfs_root/first_fs$ vi etc/init.d/rcS
book@book-desktop:/work/nfs_root/first_fs$ cat etc/init.d/rcS
#mount -t proc none /proc
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
实验一下:
book@book-desktop:/work/nfs_root/first_fs$ cd ..
book@book-desktop:/work/nfs_root$ mkyaffs2image first_fs first_fs.yaffs2
下载到开发板
到这里最小根文件系统已经很完善了
三:制作jffs2映像文件,完善最小根文件系统
1、制作工具
先删掉重新做:
book@book-desktop:/work/GUI/xwindow$ cd /work/GUI/xwindow/X/deps
book@book-desktop:/work/GUI/xwindow/X/deps$ ls
expat-2.0.1.tar.gz libdrm-2.3.0.tar.bz2 openssl-0.9.8g.tar.gz
fontconfig-2.5.0.tar.gz libpng-1.2.23.tar.bz2 zlib-1.2.3
freetype-2.3.5.tar.bz2 libxml2-2.6.30.tar.gz zlib-1.2.3.tar.gz
book@book-desktop:/work/GUI/xwindow/X/deps$ cd zlib-1.2.3/
book@book-desktop:/work/GUI/xwindow/X/deps/zlib-1.2.3$ cd ..
book@book-desktop:/work/GUI/xwindow/X/deps$ rm -rf zlib-1.2.3
book@book-desktop:/work/GUI/xwindow/X/deps$ tar xzf zlib-1.2.3.tar.gz
book@book-desktop:/work/GUI/xwindow/X/deps$ cd zlib-1.2.3/
book@book-desktop:/work/GUI/xwindow/X/deps/zlib-1.2.3$ ./configure --shared --prefix=/usr
book@book-desktop:/work/GUI/xwindow/X/deps/zlib-1.2.3$ make
book@book-desktop:/work/GUI/xwindow/X/deps/zlib-1.2.3$ sudo make install
book@book-desktop:/work/GUI/xwindow/X/deps/zlib-1.2.3$ cd ..
book@book-desktop:/work/GUI/xwindow/X/deps$ cd /work/tools/
book@book-desktop:/work/tools$ tar xjf mtd-utils-05.07.23.tar.bz2
book@book-desktop:/work/tools$ cd mtd-utils-05.07.23/util/
book@book-desktop:/work/tools/mtd-utils-05.07.23/util$ make
book@book-desktop:/work/tools/mtd-utils-05.07.23/util$ sudo make install
book@book-desktop:/work/tools/mtd-utils-05.07.23/util$ cd /work/nfs_root/
book@book-desktop:/work/nfs_root$ mkfs.jffs2 -n -s 2048 -e 128KiB -d first_fs -o first_fs.jffs2
下载实验:
下载后我们还是以yaffs文件系统启动,显然是不行的,我们要设置一下参数:
原来的参数:bootargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0
OpenJTAG> set bootargs noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0
OpenJTAG> save
OpenJTAG> boot
VFS: Mounted root (jffs2 filesystem).
四、NFS
1、配置开发板IP
# ifconfig eth0 up
# ifconfig
# ifconfig eth0 192.168.1.11
# ping 192.168.1.51
PING 192.168.1.51 (192.168.1.51): 56 data bytes
64 bytes from 192.168.1.51: seq=0 ttl=64 time=5.073 ms
2、手工挂接
a、从flash上启动根文件系统,再用命令挂接NFS
挂接NFS条件:①服务器“允许”那个目录可被挂接
②单板去挂接
book@book-desktop:/work/nfs_root/first_fs$ sudo vi /etc/exports
/work/nfs_root/first_fs *(rw,sync,no_root_squash)
重启
book@book-desktop:/work/nfs_root/first_fs$ sudo /etc/init.d/nfs-kernel-server restart
实验自己挂接自己:
book@book-desktop:/work/nfs_root/first_fs$ sudo mount -t nfs 192.168.1.51:/work/nfs_root/first_fs /mnt
单板挂接:
# mkdir /mnt
# mount -t nfs -o nolock 192.168.1.51:/work/nfs_root/first_fs /mnt
# ls /mnt
bin etc linuxrc sbin usr
dev lib proc sys
比如我们在/work/nfs_root/first_fs下创建一个文件,在单板上能够立刻看到这个文件:
book@book-desktop:/work/nfs_root/first_fs$ echo hello > test.txt
book@book-desktop:/work/nfs_root/first_fs$ ls
bin dev etc lib linuxrc proc sbin sys test.txt usr
# ls /mnt
bin etc linuxrc sbin test.txt
dev lib proc sys usr
# cat /mnt/test.txt
hello
b、直接从NFS启动:
NFS启动参数:①服务器IP,目录。 ②
重启可以看到启动参数:
bootargs=noinitrd root=/dev/mtdblock3 rootfstype=jffs2 init=/linuxrc console=ttySAC0
修改启动参数:在linux-2.6.22.6\Documentation的nfsroot.txt里面有参数的说明
nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>]
ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>
bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.51:/work/nfs_root/first_fs ip=192.168.1.11:192.168.1.51:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
OpenJTAG> set bootargs noinitrd root=/dev/nfs nfsroot=192.168.1.51:/work/nfs_root/first_fs ip=192.168.1.11:192.168.1.51:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC0
OpenJTAG> save
OpenJTAG> boot
到这里网络文件系统已经搭建好了,这样你可以在服务器上面编辑代码,编译,然后在单板上面运行了。