tiny linux -- 制作linux 小系统的方法(翻译)

 

原链接地址:

https://github.com/ir193/tiny_linux/blob/master/NOTE.md

制作小系统的思路。

正文开始

=================================================================================


This is my note of doing the project for advanced operating systems. I'll try to log tools needed, the configure I used and the pitfalls during the this project.

这是我做小系统的笔记。我尽努力记下过程中所使用的工具,配置和遇到的坑。

We’ll be building:

 1. A tiny custom [Linux kernel][1]. And try to make its size as small as possible by disable some kernel feature/function, and also by patch the kernel source code.

 2. A ramdisk served as main filesystem, with some configure to setup network working.
 
我们的目标:
1. 一个基于linux的小系统。尽量的去掉内核的多余特性和功能,及源码补丁。

2. ramdisk作为文件系统, 带网络功能。

The host and target will both be x86.

宿主机和目标机都是x86系统。

Some useful tutorial:

* http://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html

* http://www.linuxfromscratch.org/

Some useful example:

* http://distro.ibiblio.org/tinycorelinux/


一些有用的教程:
* http://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html

* http://www.linuxfromscratch.org/

有用的例子:

* http://distro.ibiblio.org/tinycorelinux/


#Preparation#
#准备工作#

Setup neccessary toolchains and libraries, at least:
安装必须的工具链和库, 至少包括:

* gcc (for building linux kernel and busybox)
* curl (for download)
* ncurses (for linux menuconfig)


Now, let's get started

现在开始

First, setup a working directory and some environment variable for convenience
首先,创建工作目录和配置环境变量

   

mkdir $HOME/tiny_linux
TOP=$HOME/tiny_linux
cd $TOP


    
Download source code of [linux kernel][1]:
下载linux内核源码和busybox源码

   

curl https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.0.4.tar.xz | tar xJf -

Downlaod source code of [busybox][2]

   

curl http://busybox.net/downloads/busybox-1.23.2.tar.bz2 | tar xjf -

#Build Linux Kernel#
#编译内核#

Now build a linux kernel with default config. Before configure&make, create a directory for obj files to keep kernel source clean and some variables for convenience
使用默认config编译linux 内核。 开始之前先创建obj文件夹存放编译后文件,以及添加一些环境变量。

   

cd $TOP
mkdir obj
mkdir obj/linux_defconfig
LINUX_SRC=$TOP/linux-4.0.4
cd $LINUX_SRC
make O=../obj/linux_defconfig i386_defconfig


    

Now the config has been write into $TOP/obj/linux_defconfig. Go into it and compile
生成的config文件放在$TOP/obj/linux_defconfig。开始编译

   

cd $TOP/obj/linux_defconfig
make

    
If no error message reported, you should see
如果没有错误的话,编好的内核文件在下面目录可以找到

> Kernel: arch/x86/boot/bzImage is ready  (#1)


Test you bright new kernel with qemu:
使用qemu测试新内核:
   

qemu-system-i386 -kernel $TOP/obj/linux_defconfig/arch/x86/boot/bzImage

    
You should see linux running and finally a kernel panic. To see full log:
linux 启动运行 最后发生 kernel panic, 完整log 使用下面命令:

    

qemu-system-i386 -kernel $TOP/obj/linux_defconfig/arch/x86/boot/bzImage -append "console=ttyS0" -nographic

    
Note that when use `-nographic`, you can quit by hit `Ctrl-C` then `a`, then type `quit`

使用`-nographic`时,退出可以按 `Ctrl-C`, 然后`a`, 然后输入`quit`

The error log should be:
错误log如下:

> [    3.711331] VFS: Cannot open root device "(null)" or unknown-block(0,0): error -6
> [    3.730405] Please append a correct "root=" boot option; here are the available partitions:


That means our kernel works fine, but it can't find root device. Next we create the root device, a ramdisk.

这个错误是正常的,说明内核已经运行,但是没有找到 root 设备。下面我们创建一个ramdisk 设备。

Before that, just copy the kernel image into obj directory.
内核最后一步,创建一个变量,方便后面调用。

   

cp $TOP/obj/linux_defconfig/arch/x86/boot/bzImage $TOP/obj
KERNEL=$TOP/obj/bzImage


#Build Root Filesystem#
#创建根文件系统#

Now we focus on the userland level, we will use [Busybox][2]. BusyBox combines tiny versions of many common UNIX utilities into a single small executable. It provides replacements for most of the utilities you usually find in GNU fileutils, shellutils, etc.

根文件系统需要用到busybox。busybox 集成了常用的文件操作和shell 命令,所有命令指向同一个可执行程序,体积小,适合小系统使用。

First we build busybox:
首先创建环境变量,生成配置文件

   

cd $TOP
mkdir obj/busybox
cd $TOP/busybox-1.23.2
make O=../obj/busybox/ defconfig

    
IMPORTANT, config busybox to static linked
【重要点】, 选择将busybox编译成静态链接

   

make O=../obj/busybox/ menuconfig


    
choose:
选择:

   

Busybox Setting:
        Build Option
            Build Busybox as a static binary

            
Ok, just build it (in obj directory, to keep source code clean)
进到obj目录,开始编译         

   

cd $TOP/obj/busybox
make
make install


    
Note that here we use a make install, but this will NOT install busybox into your HOST system. Relax.

注意:执行make install 并不是将busybox安装到你的宿主机,所以放轻松。

You can simplely run the busybox to test if it works properly.
执行命令测试编译的busybox:
   

./busybox ls

    
Now create another directory to hold our filesystem hierarchy, and copy busybox into it.
现在创建一个目录用于保存filesystem,
a. 拷贝busybox。
   

cd $TOP/
mkdir ramdisk
cd ramdisk
cp -av $TOP/obj/busybox/_install/* .

    
Then create a simple init script for debug.

    b. 建一个init文件,测试用

Recall what we learn on class, [init][3] process is the first userspace process. It takes care of services, runlevels and so on. All processes will fork from init. In real linux distribution, some typical init process are: systemd, Upstart, SysV

init 是用户空间的第一个进程。负责启动服务和运行等级等,其他所有的进程都由init启动。
在真实的linux发行版,典型的init进程包括:systemd, Upstart, SysV

    

echo -e '#!/bin/sh \n /bin/sh' > init
chmod +x init

    
To ensure kernel can execute script, we need linux kernel compiled with
linux内核运行脚本,需要修改编译选项:

   

Kernel support for scripts starting with #!


But when finish debug, we will use symbolic link busybox as init, then this option can be turned off.

但是稍后,我们将使用busybox软链接作为init,所以可以不选。

check again the symbolic link is correct. Then we can pack the filesystem into a cpio file.
确保软链接正确, 然后打包文件系统成cpio文件。

   

cd $TOP/ramdisk
find . -print0 | cpio --null -ov --format=newc | gzip -9 > $TOP/obj/initramfs.cpio.gz
RAMDISK=$TOP/obj/initramfs.cpio.gz

    
    
RUN IT~:
运行下面命令:

   

qemu-system-i386 -kernel $KERNEL -initrd $RAMDISK

If success, a shell will be ready when finish booting.
如果成功, 启动后可以输入shell命令
If you saw:

> /bin/sh: can't access tty; job control turned off

Don't worry, that's normal because our init simply launch a shell without necessary setup. We work on it in next step.
不用担心,这是由于我们没有安装sh,接下来将解决。

#Userland: init and mount#
#用户模式: init和mount#

We step back and remove the debug script. And create a symbolic link with busybox to subtitude it:
创建一个busybox到init的软链接

   

cd $TOP/ramdisk
rm init
ln -s bin/busybox init

So after kernel booting into userland, busybox will be called as init. Then busybox check configurations and do its job.
这样当kernel切换到用户模式, busybox 将被调用。 busybox将检查配置并做相应操作。

Before we write init configurations, we create some directory:
创建一些文件夹:

   

cd $TOP/ramdisk
mkdir -pv {bin,sbin,etc,proc,sys,usr/{bin,sbin},dev}

That's more like a real linux system.
这样更像真实的操作系统。

Then busybox configuration:
busybox的配置文件:
    
   

cd $TOP/ramdisk
cd etc
vim inittab

The content of inittab can be:
inittab的内容
   

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

::askfirst:-/bin/sh

::restart:/sbin/init

::ctrlaltdel:/sbin/reboot

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

::shutdown:/sbin/swapoff -a


And rcS:
rcS的内容:

   

mkdir init.d
cd init.d
vim rcS

rcS will called after system init, we mount filesystem and initialize network here
rcS 在系统启动后调用,可以用来挂载文件系统和初始化网络
   

#!/bin/sh

mount proc
mount -o remount,rw /
mount -a

clear                               
echo "Booting Tiny Linux"

Don't forget attribute:
添加可执行权限:
    
   

chmod +x rcS

See the `mount -a`, it will check /etc/fstab. We create it:
`mount -a` 用到 /etc/fstab, 建一个:

   

cd $TOP/ramdisk/etc
vim fstab

The content:
 /etc/fstab 的内容:
 
   

# /etc/fstab
proc            /proc        proc    defaults          0       0
sysfs           /sys         sysfs   defaults          0       0
devtmpfs        /dev         devtmpfs  defaults          0       0

OK for now, that's finish, pack it and run:
OK ,阶段性完成,打包运行试试:

   

cd $TOP/ramdisk
find . -print0 | cpio --null -ov --format=newc | gzip -9 > $TOP/obj/initramfs.cpio.gz
qemu-system-i386 -kernel $KERNEL -initrd $RAMDISK

We should see:
看到下面打印,成功!
   

Booting Tiny Linux
Please press Enter to activate this console.

Press Enter and get a shell. Check /dev /proc and /sys
看看下面几个目录。
   

ls /dev
ls /proc
ls /sys

Result should not be empty
不是空文件夹。
Finally, check ethernet card driver working:
最后查看网卡工作状态:
   

ifconfig -a

We should see `eth0` if ethernet card driver success.
看看有没有`eth0`

#Network#
#网络#

Keep editing /etc/init.d/rcS, add
向/etc/init.d/rcS,添加下面命令   

/sbin/ifconfig lo 127.0.0.1 up
/sbin/route add 127.0.0.1 lo &


ifconfig eth0 up
ip addr add 10.0.2.15/24 dev eth0
ip route add default via 10.0.2.2

That's all.
以上。
Check our /etc/init.d/rcS again, it should contains:
完整的/etc/init.d/rcS文件:
   

#!/bin/sh

mount proc
mount -o remount,rw /
mount -a

clear                               
echo "Booting Tiny Linux"

/sbin/ifconfig lo 127.0.0.1 up
/sbin/route add 127.0.0.1 lo &

ifconfig eth0 up
ip addr add 10.0.2.15/24 dev eth0
ip route add default via 10.0.2.2

You can test it in your tiny system:
输入下面命令测试网络:
   

wget http://[you HOST os ip]:port/file


#Reducing the kernel size#
#减少内核大小#

run
运行下面命令:

   

cd $TOP/linux-4.0.4
make O=../obj/linux_defconfig menuconfig

turn off unneccessary features! Especially devices drivers
去掉不需要的功能, 尤其是驱动部分

To be continued
下面网站,获取更多信息
see http://elinux.org/Work_on_Tiny_Linux_Kernel


#A very tiny version#
#超小版本#

start over from zero config
首先关掉所有功能

   

cd $TOP/linux-4.0.4
make O=../obj/linux_defconfig allnoconfig

This will select no to all config. Then we should turn necessary option on.
上面命令关掉所有配置,然后按需打开。
For now, at least following options:
但至少包含下面选项:

Support for basic start up and debug log:
基本的启动选项和调试log:

>
>  General setup  --->
>    Initial RAM filesystem and RAM disk (initramfs/initrd) support
>    Support initial ramdisks compressed using gzip
>    Optimize for size
>    Embedded system
>    Configure standard kernel features (expert users) -->
>      Enable support for printk

>  Executable file formats / Emulations  --->
>    Kernel support for ELF binaries
>    Kernel support for scripts starting with #!


Support Ethernet card:
网卡支持:

>  Bus options (PCI etc.)  --->
>    PCI support
>    

>

>  Networking support -->
>    Networking options -->
>       TCP/IP networking
>       INET: socket monitoring interface

>  Device Drivers -->
>    Network device -->
>       Network core driver support
>    Ethernet driver support -->
>       Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support

 

Some option depends on other options in order to be visible. Press / to see dependcy.
选项之间存在依赖关系,输入 / 可以查看。

#FAQ#
#FAQ#

1. I can't use `make menuconfig`
`make menuconfig` 不可用
Maybe you need install ncurse
安装 ncurse 试试

2. How can I see full log?
qemu-system-i386 查看完整启动log,使用下面命令
   

qemu-system-i386 -kernel $TOP/obj/linux_defconfig/arch/x86/boot/bzImage -append "console=ttyS0" -nographic

or inside you GUEST OS
或者进入系统后使用下面命令

   

dmesg | less

3. When I run qemu `error reading initrd: No such file or directory`
找不到 initrd?

Maybe you continue your work in anther shell? Check environment variable $TOP $KERNEL $RAMDISK is correct
先看看环境变量是否正确, 终端输入的变量,只在当前终端有效; 或者你可以使用完整文件路径

4. VFS: Cannot open root device "(null)"
启动根文件系统失败

check -initrd parameter and kernel compiled with initramfs support.
检查 -initrd 参数 和 内核编译是否支持 initramfs。

5. Kernel panic at boot: not syncing. No init found.

check busybox must be *staticaly* compiled
busybox 必须静态编译。

6. Generate ramdisk is slow and very large
生成ramdisk 慢又大

Execute command right under ramdisk root.
在ramdisk root下执行命令。

7. ifconfig report /proc/net/dev: No such file or directory
ifconfig 报 /proc/net/dev: No such file or directory

/proc is not properly mount. check fstab and rcS.
/proc 没有挂载成功,检查fstab 和 rcS。 也许是 windows 和 linux 格式的问题。

8. I can't see eth0
没有eth0

check ethernet device driver support. By default, QEMU emulate a Intel E1000 card. Note <M> means loadable kernel module and need mannually load.
检查网卡驱动是否支持,QEMU会仿真一个Intel E1000网卡, 如果内核是按模块编译的需要用户手动挂载。

9. I can't ping
ping功能

It's normal. Because QEMU default ethernet driver doesn't support ICMP.
QEMU 网卡驱动不支持 ICMP ,没有ping 功能。

10. A lot of error message
很多错误消息

It's normal as long as network can work.
看看网络能不能正常工作。

11. I can't get DHCP working
DHCP 不可用

NEITHER CAN I!
我的也是

12. But I can get DHCP working?
你行

DO tell me!
教下

#Reference#
#参考#

https://www.kernel.org/

http://busybox.net/

http://en.wikipedia.org/wiki/Inithttp://elinux.org/Work_on_Tiny_Linux_Kernel

http://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html

http://distro.ibiblio.org/tinycorelinux/

 

[1]: https://www.kernel.org/
[2]: http://busybox.net/
[3]: http://en.wikipedia.org/wiki/Init

[4]: http://elinux.org/Work_on_Tiny_Linux_Kernel
[5]: http://mgalgs.github.io/2015/05/16/how-to-build-a-custom-linux-kernel-for-qemu-2015-edition.html
[6]: http://distro.ibiblio.org/tinycorelinux/

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值