在centOS7.3下编译、裁剪内核

在centOS7.3下编译、裁剪内核

1.安装虚拟机,增加一块20G的SCCI用来存编译的中间文件和需要安装的软件包,增加一块10G的SATA硬盘用来安装最终的linux系统(最后作为虚拟机的第一启动项)

2.安装软件包(为了解决编译过程中的软件依赖)

yum install bison flex ncurses* elfutils-devel openssl* bc -y
  1. 格式化第2块20G的硬盘,并挂载
[root@localhost ~]# fdisk /dev/sdb    #sda sdb sdc sdb为我另加的一块20G的磁盘,用作装编译过程中的软件和中间文件


欢迎使用 fdisk (util-linux 2.32.1)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

设备不包含可识别的分区表。
创建了一个磁盘标识符为 0x5d5fd771 的新 DOS 磁盘标签。

命令(输入 m 获取帮助):p
Disk /dev/sdb:20 GiB,21474836480 字节,41943040 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0x5d5fd771

命令(输入 m 获取帮助):n
分区类型
   p   主分区 (0个主分区,0个扩展分区,4空闲)
   e   扩展分区 (逻辑分区容器)
选择 (默认 p):

将使用默认回应 p。
分区号 (1-4, 默认  1): 
第一个扇区 (2048-41943039, 默认 2048): 
上个扇区,+sectors 或 +size{K,M,G,T,P} (2048-41943039, 默认 41943039): 

创建了一个新分区 1,类型为“Linux”,大小为 20 GiB。

命令(输入 m 获取帮助):w
分区表已调整。
将调用 ioctl() 来重新读分区表。


正在同步磁盘。

[root@localhost ~]# partprobe    #发现分区
[root@localhost ~]# mkfs.xfs -f /dev/sdb1  #重新格式化
meta-data=/dev/sdb1              isize=512    agcount=4, agsize=1310656 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1
data     =                       bsize=4096   blocks=5242624, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
[root@localhost ~]# mkdir -pv /diy/    #创建被挂载的目录
[root@localhost ~]# mount /dev/sdb1 /diy/    #将这块硬盘挂载到该目录下

4.准备相关的软件包

wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/binutils/binutils-2.30.tar.xz
wget -c http://ftp.clfs.org/pub/clfs/conglomeration/bootscripts-clfs-embedded/bootscripts-clfs-embedded-1.0-pre5.tar.bz2
wget -c https://busybox.net/downloads/busybox-1.28.3.tar.bz2
wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.xz
wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/glibc/glibc-2.27.tar.xz
wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/gmp/gmp-6.1.2.tar.bz2
wget -c https://mirror.bjtu.edu.cn/kernel/linux/kernel/v4.x/linux-4.16.3.tar.xz
wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/mpc/mpc-1.1.0.tar.gz
wget -c https://mirror.tuna.tsinghua.edu.cn/gnu/mpfr/mpfr-4.0.1.tar.xz
wget -c http://www.zlib.net/zlib-1.2.11.tar.gz


4.配置编译前的shell环境

[root@localhost diy]# set +h
[root@localhost diy]# umask 022  #创建文件默认的掩码
[root@localhost diy]# export LJOS=/diy/os
[root@localhost diy]# mkdir -pv ${LJOS}
mkdir: 已创建目录 '/diy/os'
[root@localhost diy]# export LC_ALL=POSIX  #导出相应的环境变量
[root@localhost diy]# export PATH=${LJOS}/cross-tools/bin:/bin/:/usr/bin  #指定现在使用的命令只能在这些里面找

5.创建构建linux的根目录结构

[root@localhost diy]#
mkdir -pv ${LJOS}/{bin,boot{,grub},dev,{etc/,}opt,home,lib/{firmware,modules},lib64,mnt}
mkdir -pv ${LJOS}/{proc,media/{floppy,cdrom},sbin,srv,sys}
mkdir -pv ${LJOS}/var/{lock,log,mail,run,spool}
mkdir -pv ${LJOS}/var/{opt,cache,lib/{misc,locate},local}

install -dv -m 0750 ${LJOS}/root
install -dv -m 1777 ${LJOS}{/var,}/tmp
install -dv ${LJOS}/etc/init.d
mkdir -pv ${LJOS}/usr/{,local/}{bin,include,lib{,64},sbin,src}
mkdir -pv ${LJOS}/usr/{,local/}share/{doc,info,locale,man}
mkdir -pv ${LJOS}/usr/{,local/}share/{misc,terminfo,zoneinfo}
mkdir -pv ${LJOS}/usr/{,local/}share/man/man{1,2,3,4,5,6,7,8}

for dir in ${LJOS}/usr{,/local}; do
    ln -sv share/{man,doc,info} ${dir}
done

6.创建交叉编译工具的目录

[root@localhost diy]# 
install -dv ${LJOS}/cross-tools{,/bin}

7.使用目标系统的/proc/ mounts的符号链接来维护目标系统的/etc/mtab文件中正确挂载的文件系统列表

[root@localhost diy]# 
ln -svf ../proc/mounts ${LJOS}/etc/mtab

8.创建目标系统的/etc/passwd文件(目标系统的用户信息)

cat > ${LJOS}/etc/passwd << "EOF"
root::0:0:root:/root:/bin/ash
EOF

9.创建目标系统的/etc/group文件(用户组信息)

cat > ${LJOS}/etc/group << "EOF"
root:x:0:
bin:x:1:
sys:x:2:
kmem:x:3:
tty:x:4:
daemon:x:6:
disk:x:8:
dialout:x:10:
video:x:12:
utmp:x:13:
usb:x:14:
EOF

10.创建目标系统的/etc/fstab ;(启动时需要挂载的文件系统的信息)

cat > ${LJOS}/etc/fstab << "EOF"
# file system  mount-point type options dump fsck
# order
rootfs          /               auto    defaults        1      1
proc            /proc           proc    defaults        0      0
sysfs           /sys            sysfs   defaults        0      0
devpts          /dev/pts        devpts  gid=4,mode=620  0      0
tmpfs           /dev/shm        tmpfs   defaults        0      0
EOF

11.创建目标系统的/etc/profile(保存了登录系统时需要配置的shell)

cat > ${LJOS}/etc/profile << "EOF"
export PATH=/bin:/usr/bin
if [ `id -u` -eq 0 ] ; then
        PATH=/bin:/sbin:/usr/bin:/usr/sbin
        unset HISTFILE
fi
# Set up some environment variables.
export USER=`id -un`
export LOGNAME=$USER
export HOSTNAME=`/bin/hostname`
export HISTSIZE=1000
export HISTFILESIZE=1000
export PAGER='/bin/more '
export EDITOR='/bin/vi'
EOF

12.设置目标系统的主机名(这个以后也可以修改)

echo "diy-test" > ${LJOS}/etc/HOSTNAME

13.设置目标系统登录时显示的标识,

cat > ${LJOS}/etc/issue<< "EOF"
LINUX DIY OS 0.1a
Kernel \r on an \m
EOF

14.设置目标系统的/etc/inittab (使用init而不是systemd)(系统启动过程的启动级别 波特率)

cat > ${LJOS}/etc/inittab<< "EOF"
::sysinit:/etc/rc.d/startup
tty1::respawn:/sbin/getty 38400 tty1
tty2::respawn:/sbin/getty 38400 tty2
tty3::respawn:/sbin/getty 38400 tty3
tty4::respawn:/sbin/getty 38400 tty4
tty5::respawn:/sbin/getty 38400 tty5
tty6::respawn:/sbin/getty 38400 tty6
::shutdown:/etc/rc.d/shutdown
::ctrlaltdel:/sbin/reboot
EOF

15.设置目标系统的/etc/mdev (用于加载驱动后,热插拔设备后,在目标系统的/dev下创建、删除设备文件)

cat > ${LJOS}/etc/mdev.conf<< "EOF"
# Devices:
# Syntax: %s %d:%d %s
# devices user:group mode
# null does already exist; therefore ownership has to
# be changed with command
null    root:root 0666  @chmod 666 $MDEV
zero    root:root 0666
grsec   root:root 0660
full    root:root 0666
random  root:root 0666
urandom root:root 0444
hwrandom root:root 0660
# console does already exist; therefore ownership has to
# be changed with command
console root:tty 0600 @mkdir -pm 755 fd && cd fd && for x in 0 1 2 3 ; do ln -sf /proc/self/fd/$x $x; done
kmem    root:root 0640
mem     root:root 0640
port    root:root 0640
ptmx    root:tty 0666
# ram.*
ram([0-9]*)     root:disk 0660 >rd/%1
loop([0-9]+)    root:disk 0660 >loop/%1
sd[a-z].*       root:disk 0660 */lib/mdev/usbdisk_link
hd[a-z][0-9]*   root:disk 0660 */lib/mdev/ide_links
tty             root:tty 0666
tty[0-9]        root:root 0600
tty[0-9][0-9]   root:tty 0660
ttyO[0-9]*      root:tty 0660
pty.*           root:tty 0660
vcs[0-9]*       root:tty 0660
vcsa[0-9]*      root:tty 0660
ttyLTM[0-9]     root:dialout 0660 @ln -sf $MDEV modem
ttySHSF[0-9]    root:dialout 0660 @ln -sf $MDEV modem
slamr           root:dialout 0660 @ln -sf $MDEV slamr0
slusb           root:dialout 0660 @ln -sf $MDEV slusb0
fuse            root:root  0666
# misc stuff
agpgart         root:root 0660  >misc/
psaux           root:root 0660  >misc/
rtc             root:root 0664  >misc/
# input stuff
event[0-9]+     root:root 0640 =input/
ts[0-9]         root:root 0600 =input/
# v4l stuff
vbi[0-9]        root:video 0660 >v4l/
video[0-9]      root:video 0660 >v4l/
# load drivers for usb devices
usbdev[0-9].[0-9]       root:root 0660 */lib/mdev/usbdev
usbdev[0-9].[0-9]_.*    root:root 0660
EOF

16.为目标机的grub2 bootloarder创建/boot/grub2/grub.cfg

mkdir -pv ${LJOS}/boot/grub2

cat > ${LJOS}/boot/grub2/grub.cfg<< "EOF"
set default=0
set timeout=5
set root=(hd0,1)
menuentry "LINUX DIY OS 0.1a" {
        linux /boot/vmlinuz-4.16.3 root=/dev/sda1 ro quiet
}
EOF

17.初始化目标机的日志文件并给它们适当的权限

touch ${LJOS}/var/run/utmp ${LJOS}/var/log/{btmp,lastlog,wtmp}
chmod -v 664 ${LJOS}/var/run/utmp ${LJOS}/var/log/lastlog

18.交叉编译器相关预处理

unset CFLAGS
unset CXXFLAGS     #删除当前shell的环境变量
export LJOS_HOST=$(echo ${MACHTYPE} | sed "s/-[^-]*/-cross/")#交叉编译工具链所需要的环境变量
export LJOS_TARGET=x86_64-unknown-linux-gnu
export LJOS_CPU=k8
export LJOS_ARCH=$(echo ${LJOS_TARGET} | sed -e 's/-.*//' -e 's/i.86/i386/') #所使用的架构
export LJOS_ENDIAN=little

19.内核头文件预处理

[root@localhost diy]#
tar xvf linux-4.16.3.tar.xz 
cd linux-4.16.3/
make mrproper     #删除以往的配置以及中间文件
make ARCH=${LJOS_ARCH} headers_check && make ARCH=${LJOS_ARCH} INSTALL_HDR_PATH=dest headers_install
#将内核头文件安装到我们的目标目录
cp -rv dest/include/* ${LJOS}/usr/include
  1. Binutils预处理(在编译过程中所使用的一些编译工具)
[root@localhost diy]# 
tar xvf binutils-2.30.tar.xz 
mkdir binutils-build
cd binutils-build/
#配置binutils
../binutils-2.30/configure --prefix=${LJOS}/cross-tools --target=${LJOS_TARGET} --with-sysroot=${LJOS} --disable-nls --enable-shared --disable-multilib

#编译(采用四线程)
make configure-host && make -j4

ln -sv lib ${LJOS}/cross-tools/lib64
make install

cp -v ../binutils-2.30/include/libiberty.h ${LJOS}/usr/include

21.静态编译gcc

[root@localhost diy]# 
tar xvf gcc-7.3.0.tar.xz 

tar xvf gmp-6.1.2.tar.bz2
mv gmp-6.1.2 gcc-7.3.0/gmp

tar xvf mpfr-4.0.1.tar.xz 
mv mpfr-4.0.1 gcc-7.3.0/mpfr

tar xvf mpc-1.1.0.tar.gz 
mv mpc-1.1.0 gcc-7.3.0/mpc

mkdir gcc-static
cd gcc-static
#配置gcc的一些参数
AR=ar LDFLAGS="-Wl,-rpath,${LJOS}/cross-tools/lib" \
../gcc-7.3.0/configure --prefix=${LJOS}/cross-tools \
--build=${LJOS_HOST} --host=${LJOS_HOST} \
--target=${LJOS_TARGET} \
--with-sysroot=${LJOS}/target --disable-nls \
--disable-shared \
--with-mpfr-include=$(pwd)/../gcc-7.3.0/mpfr/src \
--with-mpfr-lib=$(pwd)/mpfr/src/.libs \
--without-headers --with-newlib --disable-decimal-float \
--disable-libgomp --disable-libmudflap --disable-libssp \
--disable-threads --enable-languages=c,c++ \
--disable-multilib --with-arch=${LJOS_CPU}

#开始编译静态版的gcc文件
make all-gcc all-target-libgcc -j4 && make install-gcc install-target-libgcc -j4
#如果编译时间不够五分钟请查看gcc 和 c++ --version

ln -vs libgcc.a `${LJOS_TARGET}-gcc -print-libgcc-file-name | sed 's/libgcc/&_eh/'`

22.编译目标机的glibc库

[root@localhost diy]# 
tar xvf glibc-2.27.tar.xz 
mkdir glibc-build
cd glibc-build
echo "libc_cv_forced_unwind=yes" > config.cache
echo "libc_cv_c_cleanup=yes" >> config.cache
echo "libc_cv_ssp=no" >> config.cache
echo "libc_cv_ssp_strong=no" >> config.cache

#glic的编译配置
BUILD_CC="gcc" CC="${LJOS_TARGET}-gcc" \
AR="${LJOS_TARGET}-ar" \
RANLIB="${LJOS_TARGET}-ranlib" CFLAGS="-O2" \
../glibc-2.27/configure --prefix=/usr \
--host=${LJOS_TARGET} --build=${LJOS_HOST} \
--disable-profile --enable-add-ons --with-tls \
--enable-kernel=2.6.32 --with-__thread \
--with-binutils=${LJOS}/cross-tools/bin \
--with-headers=${LJOS}/usr/include \
--cache-file=config.cache

#编译glibc库
make -j4 && make install_root=${LJOS}/ install

23.动态编译最终的gcc

[root@localhost diy]# 
mkdir gcc-build
cd gcc-build

AR=ar LDFLAGS="-Wl,-rpath,${LJOS}/cross-tools/lib" \
../gcc-7.3.0/configure --prefix=${LJOS}/cross-tools \
--build=${LJOS_HOST} --target=${LJOS_TARGET} \
--host=${LJOS_HOST} --with-sysroot=${LJOS} \
--disable-nls --enable-shared \
--enable-languages=c,c++ --enable-c99 \
--enable-long-long \
--with-mpfr-include=$(pwd)/../gcc-7.3.0/mpfr/src \
--with-mpfr-lib=$(pwd)/mpfr/src/.libs \
--disable-multilib --with-arch=${LJOS_CPU}

make -j4 && make install
--------------------------------------------------------------------------------------
cp -v ${LJOS}/cross-tools/${LJOS_TARGET}/lib64/libgcc_s.so.1 ${LJOS}/lib64

24.修改新的shell环境变量
把和编译相关的环境变量全部都换成刚才创建的交叉编译工具链

[root@localhost diy]# 
export CC="${LJOS_TARGET}-gcc"
export CXX="${LJOS_TARGET}-g++"
export CPP="${LJOS_TARGET}-gcc -E"
export AR="${LJOS_TARGET}-ar"
export AS="${LJOS_TARGET}-as"
export LD="${LJOS_TARGET}-ld"
export RANLIB="${LJOS_TARGET}-ranlib"
export READELF="${LJOS_TARGET}-readelf"
export STRIP="${LJOS_TARGET}-strip"

下面的操作为编译DIYlinux系统所需要的软件
25.编译目标机busybox

[root@localhost diy]# 
tar xvf busybox-1.28.3.tar.bz2
cd busybox-1.28.3
#采用默认配置
make CROSS_COMPILE="${LJOS_TARGET}-" defconfig
#对busybox进行编译
make CROSS_COMPILE="${LJOS_TARGET}-" -j4
#将编译出的命令安装到目标系统的文件夹
make CROSS_COMPILE="${LJOS_TARGET}-" CONFIG_PREFIX="${LJOS}" install
#把busybox提供的一个脚本拷贝到交叉编译工具链的目录中
#这个脚本用作选择系统需要的模块
cp -v examples/depmod.pl ${LJOS}/cross-tools/bin

chmod 755 ${LJOS}/cross-tools/bin/depmod.pl

26.编译linux内核

[root@localhost diy]# 
#重新进入内核目录进行内核编译
cd ../linux-4.16.3
#使用内核默认的配置
make ARCH=${LJOS_ARCH} CROSS_COMPILE=${LJOS_TARGET}- x86_64_defconfig
#对内核进行编译
make ARCH=${LJOS_ARCH} CROSS_COMPILE=${LJOS_TARGET}- -j4
#把内核相关的驱动模块安装在目标目录
make ARCH=${LJOS_ARCH} \
CROSS_COMPILE=${LJOS_TARGET}- \
INSTALL_MOD_PATH=${LJOS} modules_install

#把内核拷贝到目标目录
cp -v arch/x86/boot/bzImage ${LJOS}/boot/vmlinuz-4.16.3
#把内核所需要的印象信息也拷贝到目标目录
cp -v System.map ${LJOS}/boot/System.map-4.16.3
#把内核所需要的配置拷贝到目标目录
cp -v .config ${LJOS}/boot/config-4.16.3

#执行busybox提供的相关脚本就可以知道系统相关模块的信息
${LJOS}/cross-tools/bin/depmod.pl \
-F ${LJOS}/boot/System.map-4.16.3 \
-b ${LJOS}/lib/modules/4.16.3

27安装启动脚本bootscripts
#从内核到启动之间的启动脚本

[root@localhost diy]# 
tar xjvf bootscripts-clfs-embedded-1.0-pre5.tar.bz2
cd bootscripts-clfs-embedded-1.0-pre5

vim Makefile

修改makefile的第22行
修改前:

install -d -m ${DIRMODE}/rc.d/{init.d,start,stop}

修改后:

install -d -m ${DIRMODE} ${EXTDIR}/rc.d/init.d
install -d -m ${DIRMODE} ${EXTDIR}/rc.d/start
install -d -m ${DIRMODE} ${EXTDIR}/rc.d/stop


#将启动脚本安装到目标目录
make DESTDIR=${LJOS}/ install-bootscripts
ln -sv ../rc.d/startup ${LJOS}/etc/init.d/rcS

28.制作目标镜像的压缩包

#先对我们的系统进行备份
cp -rf ${LJOS}/ ${LJOS}-copy
#交叉编译工具链和静态编译的库是不需要的
rm -rfv ${LJOS}-copy/cross-tools
#删除内核相关的源代码
rm -rfv ${LJOS}-copy/usr/src/*


#删除运行环境上所有的静态库
FILES="$(ls ${LJOS}-copy/usr/lib64/*.a)"

for file in $FILES; do
rm -f $file
done

#将我们新拷贝的这个系统全部换为root用户和root组
chown -R root:root ${LJOS}-copy
#修改日志文件的组id
chgrp 13 ${LJOS}-copy/var/run/utmp ${LJOS}-copy/var/log/lastlog
#在新建的系统下面创建垃圾桶和控制台
mknod -m 0666 ${LJOS}-copy/dev/null c 1 3
mknod -m 0600 ${LJOS}-copy/dev/console c 5 1
#修改busybox的执行权限
chmod 4755 ${LJOS}-copy/bin/busybox

cd ${LJOS}-copy
#将整个目录进行打包压缩
tar cJf ../diy-build.tar.xz *

29.设置目标硬盘(10GB的sata硬盘划分分区,就划分1个分区)划分分区

[root@localhost ~]# 
fdisk /dev/sdc
#发现分区
partprobe
#强制格式化为ext4
mkfs.ext4 /dev/sdc1
#把这个硬盘挂载出来
mkdir -pv /newdisk
mount /dev/sdc1 /newdisk

#把我们的压缩包解压到这个盘中
cd /newdisk/
[root@localhost newdisk]# 
tar xJf /diy/diy-build.tar.xz 

#在我们的sata盘里面装一个bootloader工具
#新建一个终端
grub2-install --root-directory=/newdisk /dev/sdc


#至此就已经安装好了系统

#接下来我们重启系统


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值