一、简要说明

    对于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接口来操作系统,并提供相应的应用程序来提供服务。

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


二、查看硬件驱动

    由于实验打算用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"

    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

    要手动配置的选项

   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


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

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

    2、为Custom安装grub

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

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

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

    

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

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

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

    3、提供内核文件

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


五、编译安装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

    (2)选项配置

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

    (3)编译并且安装

    # make        # make install

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

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

    (5)为custom创建完整的rootfs

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

    (6)测试系统

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


六、为系统提供基本配置

    注意,一切配置都是在/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` #生成密码

       文件内容: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

    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

    4、预告测试一下dropbear

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

     # dropbear -p 22022

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

    5、移植dropbear到custom系统上

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

    # ls /usr/local/bin

    # 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` 查看依赖的库文件

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

    # 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

    • 移植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为如下内容

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

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

    (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

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


八、安装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

    # 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

        # 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` #生成密码

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

    (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


九、为网络提供配置文件

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

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

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

        IPADDR=192.168.1.200            NETMASK=255.255.255.0        GATEWAY=192.168.1.1

    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