一、简要说明

    对于linux发行版来说,它们很多版本都做得非常好,使用起来也很方便。但是,它们为了支持更多的硬件,更多的服务,附带了很多我们不必要用到的东西,那我们是否可以自己专门为自己的一台机器来定义内核呢?于是,一段旅途就开始了。。。

    操作系统的启动过程是这样的:

POST(加电自检) --> (BIOS)boot sequence(设置启动项) --> MBR(bootloader)(加载磁盘上的MBR) --> kernel + ramdisk(加载内核) --> mount rootfs (ro)(挂载根文件系统) --> /sbin/init (CentOS 5: /etc/inittab, CentOS6 /etc/init/*.conf) 设定默认运行级别 --> 使用/etc/rc.d/rc.sysinit初始化系统 --> 分别启动并关闭指定服务 --> Ctrl+Alt+Delete组合键 --> 启动字符终端。

    而从下图的计算机系统组成可以看出,我们要为机套提供内核,在内核上提供库文件,提供shell接口来操作系统,并提供相应的应用程序来提供服务。

clip_p_w_picpath001

    针对于我们自己的内核,只需要集成特定的硬件驱动,针对我们要使用的功能编译相应的功能就可以,所以内核的大小会非常小。


二、查看硬件驱动

    由于实验打算用VMware来进行,不是用真正的物理机,所以直接在一台装好系统的机器上查看硬件就可以了。而实际中,要针对于拥有的硬件查看手册,标签等等来得知自己各个硬件组成是什么。

先在已经安装好CentOS6.5的虚拟机中查看VMware为我们模拟的硬件平台:


    1、查看CPU类型

# cat /proc/cpuinfo

    clip_p_w_picpath002

    2、查看pci硬件类型

# lspci

clip_p_w_picpath003

    clip_p_w_picpath004    于是可以可以知道,VMware为我们虚拟出来的硬件,CPU是我们的物理CPU(英特尔的core I5系列处理器),IDE硬件是Intel 82371,SCSI硬盘是Funsion-MPT Dual Ultra320,网卡类型是Inter 82545EM的千兆网卡。



三、编译内核(linux-3.13.6)

    1、提供编译环境

        在编译主机的CentOS6.5系统上直接安装好跟编译相关的包组

 # yum groupinstall "Development tools" "Server Platform Development"

clip_p_w_picpath005

    2、编译环境的准备

    # tar -xf linux-3.13.6.tar.xz -C /usr/src/    
    # cd /usr/src/
    # ln -sv linux-3.13.6 linux
    # cd linux
    # make allnoconfig    (由于我们要手动配置内核,所以先运行allnoconfig全部回答为no选项,然后我们再进行手动开启我们要在内核中编译的功能)


    3、内核功能的配置

  # make menuconfig


clip_p_w_picpath006

    要手动配置的选项

   64-kit kernel    
    Ceneral setup
        --> Local version - append to kernel release
        --> System V IPC
    Enable loadable module support
        --> Module unloading
    Enable the block layer
        --> Block layer SG support v4
    Processor type and features
        --> Symmetric multi-processing support
        --> Processor family
            --> Core 2/newer Xeon
        --> Multi-core scheduler suppor
    Bus options (PCI etc.)
        --> PCI support
    Executable file formats / Emulations
        --> Kernel support for ELF binaries
        --> Kernel support for scripts starting with #!
    Networking support
        --> Networking options
            --> Unix domain sockets
            --> TCP/IP networking
    Device Drivers
        --> Generic Driver Options
            --> Maintain a devtmpfs filesystem to mount at /dev
            --> Automount devtmpfs at /dev, after the kernel mounted the rootfs
        --> SCSI device support
            --> SCSI device support
            --> SCSI disk support
        --> Fusion MPT device support
            --> Fusion MPT ScsiHost drivers for SPI
            --> Fusion MPT logging facility
        --> Network device support
            --> Ethernet driver support
                --> Intel devices
                    --> Intel(R) PRO/1000 Gigabit Ethernet support
                    --> Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support
        --> Input device support
            --> Mouse interface
            --> Keyboards
            --> Mice
        --> USB support
            --> xHCI HCD (USB 3.0) support
            --> EHCI HCD (USB 2.0) support
            --> OHCI HCD (USB 1.1) support
            --> UHCI HCD (most Intel and VIA) support
    File systems
        --> The Extended 4 (ext4) filesystem


    4、编译内核

     # make bzImage -j 4



clip_p_w_picpath007



四、为VMware模拟的机器安装bootload(grub)

    1、创建一个虚拟机Custom(操作过程不显示)

clip_p_w_picpath008


    2、为Custom安装grub

        为了可以安装grub,需要将Custom的硬盘挂载到一台已经装好CentOS6.5的主机,进行安装。

clip_p_w_picpath009

    注意,当CentOS6.5开机的时候,Custom不能同时开机,不然VMware会出现错误。

    然后对Custom的硬盘进行分区,创建两个分区50M和500M,50M将来做boot分区,500M将来作根分区。

clip_p_w_picpath010

    

    将它们格式化(ext4),并且分别挂载到CentOS6的/mnt/boot和/mnt/sysroot

clip_p_w_picpath011


    然后直接安装grub到custom的硬盘上(也就是sdb)

clip_p_w_picpath012


    然后为grub提供配置文件,放到/mnt/boot/grub/grub.conf

clip_p_w_picpath013


    3、提供内核文件

    最后将编译好的内核放到/mnt/boot/下面,命名为跟grub.conf中一样的内核名称

clip_p_w_picpath014



五、编译安装busybox

    1、busybox简介

    BusyBox 将许多具有共性的小版本的UNIX工具结合到一个单一的可执行文件,它包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。这样的集合可以替代大部分常用工具比如的GNU fileutils , shellutils等工具,BusyBox提供了一个比较完善的环境,可以适用于任何小的嵌入式系统。


    2、编译安装busybox到custom

    (1)配置busybox

    # yum install glibc-static 以静态的方式编译busybox依赖于这个库    
    # tar -xf busybox-1.22.1.tar.bz2
    # cd busybox-1.22.1
    # make menuconfig


clip_p_w_picpath015

    (2)选项配置

    Busybox Settings        
        --> Build Options
        --> Build BusyBox as a static binary (no shared libs) 让它支持静态编译



    (3)编译并且安装

    # make    
    # make install


clip_p_w_picpath016


    (4)复制busybox的程序到custom的根文件系统上

    # cp -a _install/* /mnt/sysroot/

clip_p_w_picpath017


    (5)为custom创建完整的rootfs

    # mkdir -p {dev,sys,proc,var/run,etc,lib,lib64,root,home,mnt,media,tmp,usr/local}

clip_p_w_picpath018


    (6)测试系统

    接下来就可以挂起CentOS6系统,启动Custom了(CentOS6挂起前千万要执行sync命令)

clip_p_w_picpath019




六、为系统提供基本配置

    注意,一切配置都是在/mnt/sysroot中


    1、提供初始化配置文件etc/inittab

  ::sysinit:/etc/rc.d/rc.sysinit #设置初始化运行的脚本
    ::respawn:/sbin/getty 19200 tty1 #设置用户登录的终端
    ::respawn:/sbin/getty 19200 tty2
    ::respawn:/sbin/getty 19200 tty3
    ::respawn:/sbin/getty 19200 tty4
    ::respawn:/sbin/getty 19200 tty5
    ::respawn:/sbin/getty 19200 tty6
    ::ctrlaltdel:/sbin/reboot #设置当用户按下ctrl+ alt + del时重启系统
    ::shutdown:/bin/umount -a -r #关机时卸载所有文件系统


    2、提供初始化配置脚本etc/rc.d/rc.sysinit

    #!/bin/sh    
    #
    #打印欢迎信息
    echo -e "Welcome to \033[34m LC Customed\033[0m linux"
    echo "Remounting root filesystem"
    mount -n -o remount,rw /dev/sda2 / #重新以读写方式挂载根文件系统
    echo "mount all filesystem"
    mount -a         #前提是要先提供了etc/fstab文件
    echo "create device file"
    mdev -s         #busybox自带的自动挂载设备文件的程序
    # 查看主机名配置文件etc/sysconfig/network,设置主机名
    [ -r /etc/sysconfig/network ] && source /etc/sysconfig/network
    [ -z "$HOSTNAME" -o "$HOSTNAME" == '(none)'] && hostname localhost || hostname $HOSTNAME

    并且要给予rc.sysinit脚本执行权限

    chmod +x etc/rc.d/rc.sysinit


    3、提供认证相关的配置文件

        提供认证的用户信息文件/etc/passwd(权限为644)

    root:x:0:0::/root:/bin/sh

        提供用户密码信息文件/etc/shadow(权限为400)

    openssl passwd -1 -salt `openssl rand -hex 4` #生成密码


clip_p_w_picpath020

       文件内容:root:生成的密码:16113:0:99999:7:::
       提供用户组文件/etc/group
       root:x:0:


        到此,关于用户认证方面的文件就配置好了!


    4、提供系统基本设置的配置文件

    提供文件系统自动挂载文件etc/fstab

    /dev/sba1 /boot ext4 defaults 0 0 #挂载boot分区
    /dev/sda2 / ext4 defaults 0 0 #挂载根分区
    sysfs /sys sysfs defaults 0 0 #挂载虚拟文件系统
    proc /proc proc defaults 0 0 #挂载虚拟文件系统

    提供用户登录配置文件etc/profile

    Export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin    
    Export PS1=PS1='[\u@\h \W]\$ '

    提供主机名配置文件etc/sysconfig/network

    HOSTNAME=mylinux.lc.net

    于是,一个简单自制的小系统完成了!




七、为系统提供远程连接功能(dropbear)

    1、dropbear简介

    Dropbear是一个相对较小的SSH服务器和客户端。它运行在一个基于POSIX的各种平台。 Dropbear是开源软件,在麻省理工学院式的许可证。 Dropbear是特别有用的“嵌入”式的Linux(或其他Unix)系统,如无线路由器。


    2、编译安装dropbear-2014.65.tar.bz2

    # tar -xf dropbear-2014.65.tar.bz2    
    # cd dropbear-2014.65
    # ./configure
    # make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp"
    # make make PROGRAMS="dropbear dbclient dropbearkey dropbearconvert scp" install

clip_p_w_picpath021


    3、为dropbear提供密钥对

    由于dropbear是ssh的一种实现,所在要为dropbear提供加密的密钥对

    # mkdir /etc/dropbear 创建配置目录,用来存放key文件    
    # /usr/local/bin/dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
    # /usr/local/bin/dropbearkey -t rsa -s 2048 -f /etc/dropbear/dropbear_rsa_host_key

clip_p_w_picpath022


    4、预告测试一下dropbear

    在移植到Custom之前,先在CentOS6.5上测试一下,由于CentOS6.5上原本就有openssh监听在22号端口,所以测试的时候要把dropbear监听在不同的端口号上,比如22022

     # dropbear -p 22022


clip_p_w_picpath023

    在 windows上用远程连接工具测试一下,比如用xshell进行测试:

clip_p_w_picpath024

    5、移植dropbear到custom系统上

    (1)移植dropbear的二进制文件

    # ls /usr/local/bin

clip_p_w_picpath025

    # cp /usr/local/bin/* /mnt/sysroot/usr/local/bin/    
    # cp /usr/local/sbin/dropbear /mnt/sysroot/usr/local/sbin/


    (2)分别移植dbclient、dropbearconvert、dropbearkey、scp、dropbear运行依赖库文件

        以dropbear为例,如何移植依赖库

     # ldd `which dropbear` 查看依赖的库文件

clip_p_w_picpath026

    移植相应的库的时候记得要先创建好对应的目录

    # cp /lib64/libutil.so.1 /mnt/sysroot/lib64/libutil.so.1    
    # cp /lib64/libz.so.1 /mnt/sysroot/lib64/libz.so.1
    # cp /lib64/libcrypt.so.1 /mnt/sysroot/lib64/libcrypt.so.1
    # cp /lib64/libc.so.6 /mnt/sysroot/lib64/libc.so.6
    # cp /lib64/libfreeb13.so /mnt/sysroot/lib64/libfreeb13.so
    # cp /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/ld-linux-x86-64.so.2
    # cp /lib64/libdl.so.2 /mnt/sysroot/lib64/libdl.so.2


    (3)为目标dropbear提供公钥对

    # mkdir /mnt/sysroot/etc/dropbear    
    # cp /etc/dropbear/* /mnt/sysroot/etc/dropbear


    (4)配置dropbear运行的相关要求

    dropbear在运行的时候,要求满足如下条件:


    • 提供安全的shell定义: /etc/shells,dropbear会来检查远程连接可使用的shell是否是安全shell

    • # vim /mnt/sysroot/etc/shells

clip_p_w_picpath027


    • 移植nsswitch:dropbear的身份验证依赖于nsswith

    # cp -a -d /lib64/libnss_files-2.12.so lib64    
    # cp -a -d /lib64/libnss_files.so.2 lib64
    # cp -a -d /usr/lib64/libnss3.so usr/lib64/
    # cp -a -d /usr/lib64/libnss_files.so usr/lib64/
    # cp -a -d /usr/lib64/libnsspem.so /usr/lib64
    # cp -a -d /usr/lib64/libnsssysinit.so /usr/lib64
    # cp -a -d /usr/lib64/libnssutil3.so /usr/lib64
  • 确保pid文件所在的目录/var/run存在

    # mkdir -pv /var/run


  • 提供devpts文件系统挂载点:为dropbear提供伪终端

        修改/mnt/sysroot/etc/rc.d/rc.sysinit为如下内容

clip_p_w_picpath028

    修改/mnt/sysroot/etc/fstab开机自动挂载pts

clip_p_w_picpath029


    (5)Custom开机之后就可以直接运行dropbear启动服务了,以后custom就可以远程连接过去

clip_p_w_picpath030

    (6)为dropbear提供控制脚本

    # vim /mnt/sysroot/etc/init.d/dropbear    
    #!/bin/bash
    #
    dbprog='/usr/local/sbin/dropbear'
    dbkeygen='/usr/local/bin/dropbearkey'
    dsskey='/etc/dropbear/dropbear_dss_host_key'
    rsakey='/etc/dropbear/dropbear_rsa_host_key'
    rsakeysize=2048
    dbport=22
    
    Gendsskey() {
        if [ ! -f $dsskey ]; then
            echo "Generating dss key file."
            [ -d /etc/dropbear ] || mkdir /etc/dropbear
            $dbkeygen -t dss -f $dsskey
        fi
    }
    
    Genrsakey() {
        if [ ! -f $rsakey ]; then
            echo "Generating rsa key file."
            [ -d /etc/dropbear ] || mkdir /etc/dropbear
            $dbkeygen -t rsa -s $rsakeysize -f $rsakey
        fi
    }
    Start() {
        gendsskey
        genrsakey
        
        if ! pidof dropbear &> /dev/null; then
            echo "Starting dropbear"
            $dbprog -p $dbport
            retval=$?
        else
            echo "$dbprog is already running..."
            return 1
        fi
        
        if [ $retval -eq 0 ]; then
            echo "OK"
            return 0
        else
            echo "Failure"
            return 1
            fi
    }
    
    Stop() {
        if pidof dropbear &> /dev/null; then
            echo "stopping dropbear"
            killall dropbear
            retval=$?
        else
            echo "$dbprog is not running ..."
            return 1
        fi
        if [ $retval -eq 0 ]; then
            echo "OK"
            return 0
        else
            echo "Failure"
            return 1
            fi
    }
    
    Status() {
        if pidof dropbear &> /dev/null; then
            echo "$dbprog is running ..."
        else
            echo "$dbprog was stopped ..."
        fi
    }
    
    Restart() {
        stop
        sleep 1
        start
    }
    
    Usage() {
        echo "Usage: `basename $0` {start|stop|restart|status}"
    }
    
    case $1 in
        start)
            start
            ;;
        stop)
            stop
            ;;
        restart)
            restart
            ;;
        Status)
            Status
            ;;
        *)
            usage
        ;;
        Esac


    为它加上运行权限    

    # chmod +x /mnt/sysroot/etc/init.d/dropbear



(7)开机自动启动服务

    在etc下面创建rc.start目录,创建init.d里各种服务软链接到此目录,在此目录有链接的服务,我们就让它自动启动

    # cd /mnt/sysroot/etc/rc.start    
    # ln -sv ../init.d/dropbear 02dropbear

clip_p_w_picpath031

    然后修改rc.sysinit脚本,让它开机自动扫描/etc/rc.start下面的链接,每一个都执行start就可以实现开机自动启动服务了。

clip_p_w_picpath032




八、安装web服务器nginx

    1、nginx简介

    Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,供俄国大型的入口网站及搜索引擎Rambler使用。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:新浪、网易、腾讯等。


    2、编译安装nginx

    # yum install pcre-devel (nginx依赖于之个开发包)    
    # useradd -M nginx (为nginx创建一个运动时使用的普通用户)
    # tar -xf nginx-1.6.1.tar.gz
    # cd nginx-1.6.1
    # ./configure --conf-path=/etc/nginx/nginx.conf --user=nginx --group=nginx

clip_p_w_picpath033

    # make && make install

    3、移植nginx

   (1)移植文件

    由编译过程可知,nginx只创建了两个目录,只要把这两个目录复制过去就可以了。

        # cp -r /usr/local/nginx /mnt/sysroot/usr/local/nginx        
        # cp -r /etc/nginx /mnt/sysroot/etc/nginx



    (2)移植nginx依赖的库文件

        # ldd /usr/local/nginx/sbin/nginx

clip_p_w_picpath034

        # cp -a -d /lib64/libpthread.so.0 /mnt/sysroot/lib64/libpthread.so.0        
        # cp -a -d /lib64/libcrypte.so.1 /mnt/sysroot//lib64/libcrypte.so.1
        # cp -a -d /lib64/libpcre.so.0 /mnt/sysroot/lib64/libpcre.so.0
        # cp -a -d /usr/lib64/libcrypto.so.10 /mnt/sysroot/usr/lib64/libcrypto.so.10
        # cp -a -d /lib64/libz.so.1 /mnt/sysroot/lib64/libz.so.1
        # cp -a -d /lib64/libc.so.6 /mnt/sysroot/lib64/libc.so.6
        # cp -a -d /lib64/ld-linux-x86-64.so.2 /mnt/sysroot/lib64/ld-linux-x86-64.so.2
        # cp -a -d /lib64/libfreebl3.so /mnt/sysroot/lib64/libfreebl3.so
        # cp -a -d /lib64/libdl.so.2 /mnt/sysroot/lib64/libdl.so.2


    (3)为nginx提供普通用户

    # openssl passwd -1 -salt `openssl rand -hex 4` #生成密码

clip_p_w_picpath035

    # vim /mnt/sysroot/etc/passwd    
    # vim /mnt/sysroot/etc/shadow
    # vim /mnt/sysroot/etc/group

clip_p_w_picpath036


    (4)为nginx提供运行脚本

#!/bin/sh    
    #
    nginx=/usr/local/nginx/sbin/nginx
    
    start() {
        if pidof $nginx &> /dev/null; then
            echo "nginx is running..."
        else
            $nginx
            echo "nginx is starting..."
        fi
    }
    
    stop() {
        if ! pidof $nginx &> /dev/null; then
            echo "nginx was stopped"
        else
            $nginx -s stop
            echo "nginx is stopping..."
    fi
    }
    
    restart() {
        stop
        start
    }
    
    reload() {
            $nginx -s reload
        echo "nginx reload OK."
    }
    
    status() {
        if pidof $nginx &> /dev/null; then
            echo "nginx is running..."
        else
            echo "nginx was stopped."
    fi
    }
    
    showversion() {
        $nginx -v       
    }
    
    configtest() {
        $nginx -t
    }
    
    usage() {
        echo "Usage: `basename $0` {start|stop|restart|reload|status|showversion|configtest}"
    }
    
    case $1 in
        start)
            start
                ;;
        stop)
            stop
            ;;
        restart)
            restart
            ;;
        reload)
            reload
            ;;
        status)
            status
            ;;
        showversion)
            showversion
            ;;
        configtest)
            configtest
            ;;
        *)
            usage
            ;;
    esac

    # chmod +x /mnt/sysroot/etc/init.d/nginx


    (5)、配置nginx开机自动启动

        只要/mnt/sysroot/etc/rc.start创建软链接就可以了

       # cd /mnt/sysroot/etc/rc.start        
       # ln -sv ../init.d/nginx ./03nginx

clip_p_w_picpath037



九、为网络提供配置文件

    1、创建/mnt/sysroot/etc/network目录用来保存网卡配置(除了lo这个网卡,它是本地循环接口,它的地址是不变)

    2、修改/mnt/sysroo/etc/init.d/rc.sysinit文件,删除掉以前的网络配置,但是本地循环接口的地址配置留下,因为它的地址是固定的,一般不手动配置

clip_p_w_picpath038

    3、在目录对应各个网卡一个配置文件(eg:eth0.conf)

        IPADDR=192.168.1.200    
        NETMASK=255.255.255.0
        GATEWAY=192.168.1.1

clip_p_w_picpath039


    4、在/mnt/sysroot/etc/init.d/创建network脚本,用来配置网络

#!/bin/bash    
    #
    stop() {
        echo "network is stopping..."
        for i in /etc/network/*; do
            dev=`basename $i | cut -d. -f1 | cut -d: -f1`
            ip addr flush $dev
        done
        echo "network stop OK."
    }
    start() {
        echo "network is starting..."
        for i in /etc/network/*; do
            source $i
            dev=`basename $i | cut -d. -f1`
            ifconfig $dev $IPADDR netmask $NETMASK
            revol=$?
    
            if [ $revol -ne 0 ]; then
                echo "ip address error!!!"
                stop
                exit 1
            fi
        done
        
        route add default gw $GATEWAY &> /dev/null
        revol=$?
        
        if [ $revol -eq 0 ]; then
            echo "network start OK..."
        else
            echo "Gateway error!!!"
            stop
        fi
    }
    
    usage() {
        echo "Usage `basename $0` {start|restart|stop}"
    }
    
    case $1 in
        start)
            start
            ;;
        restart)
            stop
            start
            ;;
        stop)
            stop
            ;;
        *)
            usage
            ;;
      esac


    5、在/etc/rc.start中创建network 的自动启动软链接,保证可以自动启动。

  # cd /mnt/sysroot/etc/rc.start    
  # ln -sv ../init.d/network 01network

clip_p_w_picpath040