一、系统启动流程:

1、POST-->BIOS(Boot Sequence)--> BootLoader(MBR)--> Kernel(initrd,initramfs)--> init (/etc/inittab)

第一步首先加电自检,计算机本身不会执行程序,由此它会载入一段程序,它会在开机时自动实现将某个RAM中的程序映射到cpu可以寻址的地址空间中去,并且可以让cpu可以执行其中的指令,而这些指令是完成系统检测的,检测完成之后,当所有的硬件或基本的核心硬件没有问题的话就进行BIOS。根据BIOS中所设定的程序启动流程去找与其对应设备上的MBR,按照引导次序执行(Boot Sequence),根据引导次序逐个查找对应的存储设备上的MBR,若MBR存在,则读取MBR上的BootLoader,BootLoader是一段程序,早期的MBR总共512字节,但它留给BootLoader空间大小是446字节,在BootLoader当中配置了所有引导的操作系统的内核的位置,因此BIOS在载入内存以后,当它实现将控制流程或控制权限转交给BootLoader以后,BootLoader就接收了整个系统的控制权限,而后根据用户的选择,去读取相应操作系统的内核。第三步:将内核装载进内核中合适的位置,解压缩并完成内核初始化,BootLoader会把控制权限转交给内核。第四步:如果内核访问根文件系统的设备需要用到某个驱动程序,而内核中也没有,就需要到根文件中去找这个驱动程序,但这文件系统本身又没有挂载,因此要想访问根文件系统得先找到驱动,要访问驱动得先找到根文件系统,这就出现了一个难题,这时就要借助于initrd,为内核提供访问真正的根文件系统所需要的基本驱动程序。因此initrd是一个辅助性的、过渡性的中间层。它能够实现将kernel与真正的根文件系统连接起来,当连接完成之后它就没有任何意义了。第五步:执行init进程,而init程序本身的配置文件是/etc/inittab(而在红帽6上init不在是传统的init,而是upstart,而upstart的配置文件在/etc/inittab和/etc/init/.*conf下的所有文件

2、(kernel)内核初始化:

硬件探测

装载驱动

挂载根文件系统(rootfs)

启动用户空间中的第一个进程init

3、init所要完成的工作主要取决于/etc/inittab,而 /etc/inittab所要完成的任务有很多:设定默认运行级别;系统初始化脚本(/etc/rc.d/rc.sysinit);运行指定级别的服务脚本:/etc/rc.d/init.d/。连接到:/etc/rc.d/rc#.d(rc0.d--rc6.d),而链接文件比较独特,有的是以K开头的文件,有的是以S开头的文件,这两种文件的后面都跟有一个数字(00-99),而这些数字是运行次序或者说是执行次序。一般来说数字越小,运行级别越高(越先被执行)。而这些链接文件都是通过chkconfig实现的。run运行指定级别的脚本完成之后,设定Ctrl、Alt、Delete三个键的意义,还有设定突然断电时怎么办?电源又恢复的时候怎么办?但这些任务对我们来说并不是最关键的,接下来启动虚拟终端、启动图形终端

4、/etc/rc.d/rc.sysinit:系统初始化,大概执行以下任务:(注意:内核在装载根文件系统时为了避免文件损坏,是以只读方式挂载的)

检测并以读写方式重新挂载根文件系统;设定主机名;检测并挂载/etc/fstab中的其它文件系统;启动swap分区;初始化外围硬件设备的驱动;根据/etc/sysctl.conf设定内核参数;**udev和selinux;**LVM和RAID设备;清理过期锁和PID文件;装载键映射;

二、制作自己的小linux:

1、学了那么久的linux了,我们也应该有一个属于自己制作的小linux了,而小linux所要实现的功能有一下几部分:

1)、关机和重启;shutdown -r now 重启;shutdown -h now:关机; halt关机; reboot重启; poweroff关机

2)、主机名;

3)、运行对应服务脚本;

4)、启动终端;

5)、运行用户;

6)、定义单用户级别;

7)、装载网卡驱动,启用网络功能;

8)、提供一个web服务器;

9)、设定内核参数;

这些做完后我们的小linux就算是真正的完成了,但我们发现这个小linux每用到一个命令都要移植,这是比较麻烦的,因为你不仅要移植命令还要移植文件所依赖的库,那接下来我们就做到linux真正的裁剪和定制。

2、我们有一个项目叫busybox,它是一个命令也是一个二进制程序,但是他有很多链接,不到1M大小,一个命令可以模拟几百个命令使用,例如你拿它当ls用,它就是ls等等、、、、我们可以使用一个1M的busybox手动制作一个内核(kernel),因此我们不需要移植太多的模块,只需要移植一些最最基本的就可以了。

下面我们就来制作一个属于自己的小linux

 

开始之前先把虚拟机安装好,这里我用的是linux-5.8的版本,安装好后,再添加一个盘进来,为了便于区别我安装了一块IDE的盘

1、创建分区(在这里我们创建2个2G的主分区)

partprobe /dev/hda #重读磁盘分区

cat /proc/partitions #查看分区列表

2、创建挂载点,mkdir /mnt/{boot,sysroot}其中hda1挂载在/mnt/boot;hda2挂载在/mnt/sysroot

mkdir /mnt/{boot,sysroot} -pv # 创建挂载点

mke2fs -j /dev/hda1 #格式化

mke2fs -j /dev/hda2

mount /dev/hda1 /mnt/boot #挂载设备

mount /dev/hda2 /mnt/sysroot

mount #查看是否挂载成功

3、切记虽然挂载好了,但挂载点里面没有任何文件,下面我们复制内核

cp /boot/vmlinuz-2.6.18-308.el5 /mnt/boot/vmlinuz

为了便于解压缩,我在这里建一个test目录

mkdir test

cd test

zcat /boot/initrd-2.6.18-308.el5.img | cpio -id

vim init #编辑配置文件

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

cd lib/ #里面有很多的dm模块,没有用,就删了

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

rm -f dm-*     #删除dm开头的模块文件

find . | cpio -H newc --quit -o | gzip -9 > /mnt/boot/initrd.gz   #(先备份出来)

ls -lh /mnt/boot/     #检验

grub-install --root-directory=/mnt /dev/hda    #安装grub

ls /mnt/boot     #校验一下是否有grub

vim /mnt/boot/grub/grub.conf #编辑配置文件

default=0

timeout=5

title my linux(2.6.18)

root (hd0,0)

kernel /vmlinuz

initrd /initrd.gz

提供真正的根文件系统

cd /mnt/sysroot

mkdir etc/rc.d/init.d bin sbin proc sys dev lib root mnt media var/{log,run,lock/subsys,tmp} usr/{bin,sbin,local} tmp home opt boot -pv #创建所需的根文件系统

vim etc/inittab # 编辑配置文件

id:3:initdefault: #设定默认运行级别

si::sysinit:/etc/rc.d/rc.sysinit #系统初始化脚本

vim etc/rc.d/rc.sysinit #编辑编辑初始化脚本

#!/bin/bash

echo -e "\tWelcome to \033[1;34mMagedu linux\033[0m"

/bin/bash #执行/bin/bash

chmod +x etc/rc.d/rc.sysinit #给配置文件执行权限

复制命令的脚本:在根目录下编辑bincp.sh

vim bincp.sh #复制二进制程序及其依赖的库文件的脚本

#!/bin/bash

#

DEST=/mnt/sysroot

libcp() {

LIBPATH=${1%/*}

[ ! -d $DEST$LIBPATH ] && mkdir -p $DEST$LIBPATH

[ ! -e $DEST${1} ] && cp $1 $DEST$LIBPATH && echo "copy lib $1 finished."

}

bincp() {

CMDPATH=${1%/*}

[ ! -d $DEST$CMDPATH ] && mkdir -p $DEST$CMDPATH

[ ! -e $DEST${1} ] && cp $1 $DEST$CMDPATH

for LIB in `ldd $1 | grep -o "/.*lib\(64\)\{0,1\}/[^[:space:]]\{1,\}"`; do

libcp $LIB

done

}

read -p "Your command: " CMD

until [ $CMD == 'q' ]; do

! which $CMD &> /dev/null && echo "Wrong command" && read -p "Input again:" CMD && continue

COMMAND=` which $CMD | grep -v "^alias" | grep -o "[^[:space:]]\{1,\}"`

bincp $COMMAND

echo "copy $COMMAND finished."

read -p "Continue: " CMD

done

chmod +x bincp.sh #给文件执行权限

复制这些命令:init,bash,ls,touch,mkdir,cat ,mount,umount,vim,vi,chmod,chown,cp,ping,route,reboot,halt,shutdown,hostname,注意每添加一个命令都要复制过来

sync(多同步几次)

验证:

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

4、新建一个虚拟机,使用我们刚才添加的IDE盘,验证一下看能否启动:

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

注意:启动小linux完成之后它无法自动完成将根文件系统挂载可读写

而mount –n:挂载时不更新/etc/mtab文件

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

我们在touch一个文件:

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

5、现在这个小系统还不能关机,重启,接下来我们就让它可以实现关机,重启的功能:切回到宿主机:给我的小系统提供脚本,来实现系统关机、重启的功能

cd /mnt/sysroot

etc/rc.d/rc.sysdone #脚本,可用于实现微型的Linux系统关机

#!/bin/bash

#

sync

sleep 2

sync

mount | awk '{print $3}' | grep -v -E "\/(dev|proc|sys)?$" | sort -r | while read LINE; do

umount -n -f $LINE

[ $? -eq 0 ] && echo "Unmount $LINE finished." || echo "Can not unmount $LINE."

done

mount | awk '{print $3}' | while read LINE; do

mount -n -o remount,ro $LINE

[ $? -eq 0 ] && echo "Remount $LINE finished." || echo "Can not remount $LINE."

done

exec /sbin/halt -p

chmod +x etc/rc.d/rc.sysdone #给脚本一个执行权限

注意每添加一个命令都要通过bincp.sh脚本复制过去

vim etc/inittab

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc.sysdone #切换到0级别时要执行/etc/rc.d/rc.sysdone

l6:6:wait:/etc/rc.d/rc.reboot #切换到6级别时要执行/etc/rc.d/rc.reboot

vim etc/rc.d/rc.reboot #编辑reboot脚本(重启脚本)

#!/bin/bash

#

sync

sleep 1

sync

exec /sbin/reboot #执行这个脚本

chmod +x etc/rc.d/rc.reboot #给执行权限

vim etc/rc.d/rc.sysdone #关机脚本

#!/bin/bash

#

sync

sleep 2

sync

exec /sbin/halt -p

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

验证关机与重启功能:

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

linux的裁剪过程,让你的小linux更加完善,赶快试试吧!

注意:注意如果在此处修改小系统,再回到宿主机,系统可能会崩溃,如果崩溃就用下面的命令修复

cd /mnt/sysroot/

find . | cpio -H newc --quiet -o | gzip > /root/sysroot.gz(把所有的大小打包起来)

cd

umount /mnt/sysroot(若卸不掉就使用fuser -km /dev/hda2)

mke2fs -j /dev/hda2 #重新格式化

mount /dev/hda2 /mnt/sysroot/ #重新挂载

cd /mnt/sysroot

zcat /root/sysroot.gz | cpio -id (展开所有打包的文件)

sync(多执行几次)

6、我们也可以用一个脚本即完成关机又完成重启:

cd /mnt/sysroot/

vim etc/rc.d/init.d/halt

#!/bin/bash

#

case $0 in

*reboot)

COMMAND='/sbin/reboot' ;;

*halt)

COMMAND='/sbin/halt -p' ;;

*)

echo "Only call this script by *reboot OR *halt;" ;;

esac

case $1 in

start) ;;

stop) ;;

*)

echo "Usage:`basename $0` {start|stop}" ;;

esac

exec $COMMAND

chmod +x etc/rc.d/init.d/halt

为halt创建链接:

cd etc/rc.d/

mkdir rc0.d rc6.d #创建两个目录

cd rc0.d/

ln -sv ../init.d/halt S99halt

cd ..

cd rc6.d/

ln -sv ../init.d/halt S99reboot

而rc.reboot rc.sysdone这时已经没用了,那我们就把它删了

rm -rf rc.sysdone rc.reboot

创建rc脚本:把所有S开头的都start,把所有K开头的都stop

vim etc/rc.d/rc

#!/bin/bash

#

RUNLEVEL=$1

for I in /etc/rc.d/rc$RUNLEVEL.d/K*; do

$I stop

done

for I in /etc/rc.d/rc$RUNLEVEL.d/S*; do

$I start

done

chmod +x etc/rc.d/rc

vim etc/inittab

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0

l3:3:wait:/etc/rc.d/rc 3 #为3级别创建目录

l6:6:wait:/etc/rc.d/rc 6

cd etc/rc.d/

mkdir rc3.d

vim etc/rc.d/init.d/tserver #脚本,测试SysV服务的定义格式:

#!/bin/bash

#

# chkconfig: 35 66 33 #通过chkconfig控制

# description: test service script

#

. /etc/rc.d/init.d/functions #这个脚本在下面

prog=tserver

lockfile=/var/lock/subsys/$prog

start() {

touch $lockfile

[ $? -eq 0 ] && success "Starting $prog" || failure "Staring $prog"

}

stop() {

rm -f $lockfile

[ $? -eq 0 ] && success "Stopping $prog" || failure "Stopping $prog"

}

status() {

if [ -f $lockfile ]; then

echo "Running..."

else

echo "Stopped..."

fi

}

usage() {

echo "Usage: $prog {start|stop|status|restart}"

}

case $1 in

start)

start ;;

stop)

stop ;;

restart)

stop

start ;;

status)

status ;;

*)

usage

exit 1 ;;

esac

chmod +x init.d/tserver

cd rc3.d #为3级别创建链接文件

ln -sv ../init.d/tserver S66tserver

ln -sv ../init.d/tserver S33tserver

vim etc/inittab #添加终端

1:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty1

2:2345:respawn:/sbin/agetty -n -l /bin/bash 38400 tty2

注意每添加一个功能都要在小系统中验证一下

7、要想让根文件系统重新挂载可读写,先编辑etc/fstab配置文件

vim etc/fstab

/dev/hda2 / ext3 defaults 0 0

/dev/hda1 /boot ext3 defaults 0 0

proc /proc proc defaults 0 0

sysfs /sys sysfs defaults 0 0

vim etc/rc.d/rc.sysinit

#!/bin/bash

#

echo -e "\tWelcome to \033[34mMageEdu\033[0m Linux"

echo "Remount rootfs..."

mount -n -o remount,rw /

echo "Set the hostname..."(设定主机名)

[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network #判定文件是否存在

[ -z $HOSTNAME -o "$HOSTNAME" == '(none)' ] && HOSTNAME=localhost #判定主机名是否存在或为空

/bin/hostname $HOSTNAME

echo "Initializing network device..."

/sbin/insmod /lib/modules/mii.ko #cp 模块以后添加进来

/sbin/insmod /lib/modules/pcnet32.ko

mkdir etc/sysconfig

vim etc/sysconfig/network

HOSTNAME=minilinux.magedu.com #添加主机名

vim etc/rc.d/init.d/functions 可用于控制服务脚本的信息显示:

SCREEN=`stty -F /dev/console size 2>/dev/null`

COLUMNS=${SCREEN#* }

[ -z $COLUMNS ] && COLUMNS=80

SPA_COL=$[$COLUMNS-14]

RED='\033[31m'

GREEN='\033[32m'

YELLOW='\033[33m'

BLUE='\033\34m'

NORMAL='\033[0m'

success() {

string=$1

RT_SPA=$[$SPA_COL-${#string}]

echo -n "$string"

for I in `seq 1 $RT_SPA`;do

echo -n " "

done

echo -e "[ ${GREEN}OK${NORMAL} ]"

}

failure() {

string=$1

RT_SPA=$[$SPA_COL-${#string}]

echo -n "$string"

for I in `seq 1 $RT_SPA`;do

echo -n " "

done

echo -e "[ ${RED}FAILED${NORMAL} ]"

}

mkdir lib/modules #创建模块文件

cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/pcnet32.ko/mnt/sysroot /lib/modules

cp /lib/modules/2.6.18-308.el5/kernel/drivers/net/mii.ko /mnt/sysroot/lib/modules/

8、添加IP地址

mkdir -pv etc/sysconfig/network-scripts #先创建目录

vim etc/sysconfig/network-scripts/ifcfg-eth0

DEVICE=eth0

BOOTPROTO=static

IPADDR=192.168.1.150

NETMASK=255.255.255.0

GATEWAY=172.16.0.1

ONBOOT=yes

vim etc/rc.d/init.d/network

#!/bin/bash

#

#chkconfig: 35 09 90

#description: network service

prog=network #定义变量

./etc/rc.d/init.d/functions #调用函数

CONF=/etc/sysconfig/network-scripts/ifcfg-eth0

.$CONF

start() {

ifconfig eth0 $IPADDR/16 up

[ -z $GATEWAY ] && route add default gw $CATEWAY

}

stop() {

ifconfig eth0 down

}

status() {

ifconfig eth0

}

usage() {

echo "$prog:{start|stop|restart|status}"

}

case $1 in

start)

success "Config network eth0" ;;

stop)

success "Stop network card eth0" ;;

restart)

stop

start

success "Restart network card eth0" ;;

status)

status ;;

*)

usage

exit 1 ;;

esac

chmod +x etc/rc.d/init.d/network #执行权限

要想能在级别0,3,6下启动,需要创建链接

cd etc/rc.d/rc0.d/

ln -sv ../init.d/network K90network

cd ../rc6.d/

ln -sv ../init.d/network K90network

cd ../rc3.d/

ln -sv ../init.d/network S09network

用户登陆时显示的信息设置

vim /mnt/sysroot/etc/issue 添加如下内容

My Linux

Kernel \r on an \m #内核版本号

设定内核参数:

vim /mnt/sysroot/etc/sysctl.conf 内容如下:

net.ipv4.ip_forward = 1

编辑/mnt/sysroot/etc/rc.d/rc.sysinit文件 添加以下内容

sysctl -p &> /dev/null #IP地址立即生效

9、添加用户功能

使用不依赖与PAM的login程序

放到/mnt/sysroot/bin/目录下,之后赋予它执行权限

登陆时是使用login程序来验证登陆的,实现用户认证是到特定的文件中去认证的,传统的方式都是

放在/etc/passwd以及/etc/shadow

nsswitch是个框架,它能够完成配置到哪个去找用户的账号及密码;nsswitch就是依靠配置文件来定义的

nsswitch这个框架由库和相对应的配置文件来组成,在配置文件中可直接定义基于哪个库去去找相应的验证文件

例如:在/ect/passwd认证所找的是libnss_file.so这样的库

vim /mnt/sysroot/etc/nsswitch.conf 内容如下:

passwd: files

shadow: files

group: files

hosts: files dns

复制库文件

cp -d /lib/libness_file* /mnt/sysroot/lib/

cp -d /usr/lib/libnss_files.so/mnt/sysroot/usr/lib/

cp -d /usr/lib/libnss3.so /usr/lib/libnssckbi.so /usr/lib/libnssutil3.so /mnt/sysroot/lib/

创建用户

这里直接从本系统上复制一个用户过来

grep -E "^root\> /etc/passwd > /mnt/sysroot/etc/passwd

grep -E "^root\> /etc/shadow > /mnt/sysroot/etc/shadow

grep -E "^root\> /etc/group> /mnt/sysroot/etc/group

修改inittab文件,现在可以改为让输入用户的登陆方式了

vim /mnt/sysroot/etc/inittab 整体内容如下内容如下:

id:3:initdefault:

si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0

l1:1:wait:/etc/rc.d/rc 1

l3:3:wait:/etc/rc.d/rc 3

l6:6:wait:/etc/rc.d/rc 6

1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2

到这里用户功能的添加就完成了。

补充:

对/mnt/sysroot/etc/rc.d/rc.sysinit配置的整体修改,来实现对界面的进一步美化,代码如下:

#!/bin/bash

#

. /etc/rc.d/init.d/functions

echo -e "\tMy\033[34mMagedu.com\033[0mLinux"

echo "Remount rootfs...."

mount -n -o remount,rw /

[ $? -eq 0 ] && success "Remount rootfs" || failure "Remount rootfs"

mount -a

[ $? -eq 0 ] && success "Mount others filesystem" || failure "Mount others filesystem"

#Set the hostname.....

[ -f /etc/sysconfig/network ] && . /etc/sysconfig/network

[ -z $HOSTNAME -o "$HOSTNAME" == '(none)' ] && HOSTNAME=localhost

/bin/hostname $HOSTNAME

[ $? -eq 0 ] && success "Set the hostname" || failure "Set the hostname"

# Initializing network device....

/sbin/insmod /lib/modules/mii.ko

/sbin/insmod /lib/modules/pcnet32.ko

[ $? -eq 0 ] && success "Initializing network device" || failure "Initialization network device"

ifconfig lo 127.0.0.1/8

[ $? -eq 0 ] && success "Activating loopback network device" || failure "Activating loopback network device"

sysctl -p &> /dev/null

[ $? -eq 0 ] && success "Set kernel parameter" || failure "Set kernel paramenter"

属于自己的小linux就做好了,虽然不是很完善,但是也很好用的,赶快试试吧!