Compare commits

...

141 Commits
v0.2 ... main

Author SHA1 Message Date
superconvert
a9dae8732d
Add files via upload 2025-03-04 12:07:10 +08:00
superconvert
3b2260fa48
Update 计算机运作原理.md 2023-06-08 22:05:20 +08:00
superconvert
afdd01da4d
Update 计算机运作原理.md 2023-06-08 22:04:30 +08:00
superconvert
4fa5e4e777
Update 初识 initramfs .md 2023-06-08 22:04:00 +08:00
superconvert
f489a35d32
Add files via upload 2023-06-08 22:02:39 +08:00
superconvert
e52c566997
Update README.md 2022-11-05 11:03:14 +08:00
superconvert
c6b21cbfa4
Update README.md 2022-10-28 05:25:59 +08:00
superconvert
3a0a5762b4 update 01_build_src.sh 2022-10-27 22:00:54 +08:00
superconvert
15374080d6 add iptables support 2022-10-27 21:06:23 +08:00
superconvert
089ef059e1 update llvm compile 2022-10-26 22:21:38 +08:00
superconvert
5d1564b38a update script 2022-10-25 23:24:44 +08:00
superconvert
b4153d2f65 update some script 2022-10-24 22:14:20 +08:00
superconvert
e9c9c533bf
Update README.md 2022-10-24 06:39:09 +08:00
superconvert
a513a34d71
Create README.md 2022-10-24 06:26:16 +08:00
superconvert
f2fd01f9d1 fixed root login on 'UNKNOWN' 2022-10-23 17:06:04 +08:00
superconvert
0b2a902a28 enable syslogd service 2022-10-23 15:15:33 +08:00
superconvert
2f5adf9e6c
Update README.md 2022-10-23 12:25:35 +08:00
superconvert
7b90a2171a upowerd can display in xfce4 smart-os 2022-10-22 18:36:23 +08:00
superconvert
7c88f91bf6 Merge branch 'main' of github.com:superconvert/smart-os into main 2022-10-22 16:48:53 +08:00
superconvert
7d2f6a77e3 upowerd now alse can run 2022-10-22 16:48:45 +08:00
superconvert
437cfed85a
Update README.md 2022-10-21 22:49:17 +08:00
superconvert
643a60907d now keyboard & mouse can work in xfce smart-os 2022-10-21 22:47:43 +08:00
superconvert
04f777b5cd can run mouse driver 2022-10-19 14:09:51 +00:00
superconvert
e87a814c50 can run xfce4 in smartosgit add *.sh! 2022-10-18 20:55:17 +08:00
superconvert
3074c3014d add openssh(sftp) && multi term login 2022-10-17 14:26:20 +00:00
superconvert
7b792a967d update script 2022-10-16 15:35:20 +08:00
superconvert
4e53696d30 update script 2022-10-16 13:37:37 +08:00
superconvert
3aa22d52d1 enable kerenl vkms support 2022-10-16 11:32:52 +08:00
superconvert
e537fbed20 Merge branch 'main' of github.com:superconvert/smart-os into main 2022-10-16 02:30:32 +00:00
superconvert
c8463bba4f add param test for mk_xfce.sh 2022-10-16 02:30:19 +00:00
superconvert
fcca13978b update common.sh 2022-10-15 19:10:38 +08:00
superconvert
1aa23da0b0 update script 2022-10-15 06:29:39 +00:00
superconvert
b1356c1b65 update script 2022-10-14 13:15:23 +00:00
superconvert
94e3e14e13 update script 2022-10-13 14:19:12 +00:00
superconvert
c4c25e8bdb update script 2022-10-10 13:19:13 +00:00
superconvert
a4c2f39987 update script 2022-10-09 13:52:51 +00:00
superconvert
15fecf743f update xfce script 2022-10-09 07:05:29 +08:00
superconvert
62d7211be2 update script 2022-10-02 18:45:28 +08:00
superconvert
64e259b360
Update xfce4.md 2022-10-02 10:08:46 +08:00
superconvert
9d956731f1 add llvm support 2022-10-01 22:33:38 +08:00
superconvert
d1a95e421c update make image script 2022-10-01 19:47:23 +08:00
superconvert
a4a40ea129
Add files via upload 2022-10-01 10:35:12 +08:00
superconvert
08a82e30ed
Update xfce4.md 2022-10-01 10:33:50 +08:00
superconvert
e1045b8901 update xfce doc 2022-10-01 02:15:23 +00:00
superconvert
054b8f577d
Update xfce4.md 2022-10-01 08:04:15 +08:00
superconvert
b5c05a5c00 xinit run xclient & xserver success 2022-09-30 12:55:47 +00:00
superconvert
b5c9d2f931 xinit run xclient & xserver success 2022-09-30 12:54:55 +00:00
superconvert
a7996afe36
Update mk_xfce.sh 2022-09-30 08:31:03 +08:00
superconvert
ac5823d539 enable xfce 2022-09-29 15:15:18 +00:00
superconvert
67524810e3 add xinit support 2022-09-29 15:14:34 +00:00
superconvert
ac52714964
Update 01_build_src.sh 2022-09-29 12:02:49 +08:00
superconvert
3f72afae09 update mk_xfce.sh 2022-09-28 14:20:39 +00:00
superconvert
e4fa469d49 add some comment for xfce4 2022-09-28 14:03:27 +00:00
superconvert
29bbb54275 Xorg had run in image 2022-09-28 13:54:06 +00:00
superconvert
d1b47387c3
Update README.md 2022-09-28 19:54:41 +08:00
superconvert
56de968b9b update script 2022-09-27 14:16:11 +00:00
superconvert
2d13af3221 update script 2022-09-26 14:00:07 +00:00
superconvert
cf7f3da1bf add xfce into image 2022-09-26 12:56:15 +00:00
superconvert
e8f34bfa38
Update 01_build_src.sh 2022-09-19 13:31:22 +08:00
superconvert
ee1daa96fe Merge branch 'main' of github.com:superconvert/smart-os into main 2022-09-17 15:10:20 +00:00
superconvert
738c64116f update script 2022-09-17 15:10:03 +00:00
superconvert
35d89a90c6
Update xfce4.md 2022-09-17 22:41:40 +08:00
superconvert
a002dfe29e update scripts 2022-09-17 06:21:44 +00:00
superconvert
3d977da3de add upowerd script 2022-09-15 15:04:22 +00:00
superconvert
8a35393138
Update xfce4.md 2022-09-15 19:52:29 +08:00
superconvert
2132acdca6
Update xfce4.md 2022-09-15 19:50:06 +08:00
superconvert
fbac185ad7 add schemas support 2022-09-14 13:21:11 +00:00
superconvert
8506de4f3d update mk_xfce.sh 2022-09-13 21:32:21 +00:00
superconvert
a740e0f0da update mk_xfce.sh 2022-09-13 14:04:57 +00:00
superconvert
e8dab70705
Update xfce4.md 2022-09-13 08:14:16 +08:00
superconvert
40f3f911dd update mk_xfce.sh 2022-09-12 15:15:31 +00:00
superconvert
788de643ba add video driver support for xfce 2022-09-12 14:04:20 +00:00
superconvert
3914f7f258 update mk_xfce.sh 2022-09-12 08:36:52 +00:00
superconvert
b003ac728b update mk_xfce.sh 2022-09-12 06:36:10 +00:00
superconvert
8da4f4e441 add gnome-icon-theme support 2022-09-12 02:34:02 +00:00
superconvert
77484ea06a update mk_xfce.sh 2022-09-12 02:06:47 +00:00
superconvert
3f6318462d add upower description 2022-09-12 02:00:18 +00:00
superconvert
008d91d445
Update xfce4.md 2022-09-12 09:49:17 +08:00
superconvert
9e7f1cef70 update mk_xfce.sh 2022-09-11 14:05:18 +00:00
superconvert
f8f29b48cb add xkbdata support 2022-09-11 14:02:04 +00:00
superconvert
00fded63ba add font & env support 2022-09-11 04:15:43 +00:00
superconvert
1c0f3e8a40 update mk_xfce.sh 2022-09-10 08:57:46 +00:00
superconvert
b322b03dfd add font support 2022-09-10 08:31:48 +00:00
superconvert
67469d3784 update mk_xfce.sh 2022-09-10 00:32:09 +00:00
superconvert
b89ba7113a add libinput comile for mk_xfce.sh 2022-09-10 00:21:18 +00:00
superconvert
7f976686d9 update mk_xfce.sh 2022-09-09 15:26:24 +00:00
superconvert
b30db2fe72 Update mk_xfce.sh 2022-09-09 14:11:21 +00:00
superconvert
435005135c update xfce4.md 2022-09-03 08:50:52 +00:00
superconvert
9ebc990f12 update mk_xfce.sh 2022-09-03 05:54:01 +00:00
superconvert
3737e997dc udpate xfce4.md 2022-09-01 15:06:14 +00:00
superconvert
d4910fc02a
Update xfce4.md 2022-09-01 22:50:17 +08:00
superconvert
9e268413e9
Update xfce4.md 2022-09-01 22:47:43 +08:00
superconvert
d3101db0e9 add xterm compile 2022-09-01 14:32:14 +00:00
superconvert
7bbca096d6 update mk_xfce.sh 2022-08-31 14:48:05 +00:00
superconvert
e16183c0e2
Update xfce4.md 2022-08-31 21:36:42 +08:00
superconvert
a42907616e
Update xfce4.md 2022-08-31 21:33:30 +08:00
superconvert
1304bb56cb
Update xfce4.md 2022-08-31 21:29:21 +08:00
superconvert
87a3f123a2 add compile xserver 2022-08-31 13:23:52 +00:00
superconvert
212b889524 update mk_xfce.sh 2022-08-29 22:07:09 +00:00
superconvert
7908dd4dbe
Update xfce4.md 2022-08-28 19:44:23 +08:00
superconvert
1d30aff8ee
Update xfce4.md 2022-08-27 07:34:03 +08:00
superconvert
97068da0d4
Update xfce4.md 2022-08-27 06:16:54 +08:00
superconvert
78b988877a
Update xfce4.md 2022-08-27 06:15:23 +08:00
superconvert
551dc04910
Update xfce4.md 2022-08-27 06:13:59 +08:00
superconvert
d48c2591e7
Update xfce4.md 2022-08-27 06:12:36 +08:00
superconvert
6a9f80fc9d
Update xfce4.md 2022-08-27 06:11:42 +08:00
superconvert
6f0f7c0b2a
Update README.md 2022-08-27 06:07:06 +08:00
superconvert
7010635d63
Update xfce4.md 2022-08-24 20:21:26 +08:00
superconvert
3f117e4747 add some lib support 2022-08-22 15:49:14 +00:00
superconvert
b93432353f Merge branch 'main' of github.com:superconvert/smart-os into main 2022-08-21 15:42:32 +00:00
superconvert
32b86194a2 add gstreamer & mesa support 2022-08-21 15:42:14 +00:00
superconvert
2a668a1e62 add libzip & libnotify support 2022-08-21 11:09:44 +00:00
superconvert
0f5e99044e update mk_xfce.sh 2022-08-21 05:33:34 +00:00
SuperConvert
eaa06dea59 update all scripts 2022-08-21 02:12:25 +00:00
SuperConvert
4ffcf2d369 update mk_xfce.sh 2022-08-20 17:40:05 +00:00
SuperConvert
f4ee0ccc7c update mk_xfce.sh 2022-08-20 00:16:34 +00:00
SuperConvert
e896ec59b4 add upower & startup-notification lib 2022-08-19 15:29:54 +00:00
superconvert
68593d5738
Update xfce4.md 2022-08-19 09:35:53 +08:00
superconvert
6358fe0e5b
Update xfce4.md 2022-08-19 09:23:12 +08:00
superconvert
9f4814d970
Update xfce4.md 2022-08-19 09:19:41 +08:00
superconvert
db0dfebf71
Update xfce4.md 2022-08-19 08:57:22 +08:00
superconvert
5330c766a9 update mk_xfce.sh 2022-08-18 22:49:24 +08:00
superconvert
6f317ff786
Update xfce4.md 2022-08-18 22:48:03 +08:00
superconvert
b26c1e2da0
Update xfce4.md 2022-08-18 22:45:58 +08:00
superconvert
b6596ae8b7
Update xfce4.md 2022-08-18 22:42:12 +08:00
superconvert
7c20939ede update xfce4 doc 2022-08-18 22:35:12 +08:00
superconvert
8b20c14682
Update xfce4.md 2022-08-18 15:55:36 +08:00
superconvert
edef2e31a4
Update xfce4.md 2022-08-18 08:06:44 +08:00
superconvert
423d7aa06a
Update xfce4.md 2022-08-18 08:05:00 +08:00
superconvert
23ee4ebf24 update some code 2022-08-18 06:43:52 +08:00
superconvert
46d18d4cf2
Update xfce4.md 2022-08-18 06:27:48 +08:00
superconvert
9aa8c878ed
Update xfce4.md 2022-08-18 06:27:14 +08:00
superconvert
f6ffd34c27
Update xfce4.md 2022-08-17 22:26:53 +08:00
superconvert
ba0a0a0243
Update xfce4.md 2022-08-17 09:17:41 +08:00
superconvert
e7746eb439
Update xfce4.md 2022-08-16 23:28:49 +08:00
superconvert
4793cb5dbe
Update xfce4.md 2022-08-16 23:28:33 +08:00
superconvert
1341bd119b
Update xfce4.md 2022-08-16 23:25:03 +08:00
superconvert
19f704325b
Update xfce4.md 2022-08-16 23:21:04 +08:00
superconvert
dde1c4f5e8
Update README.md 2022-08-16 23:18:29 +08:00
superconvert
0d4c5932bc
Update README.md 2022-08-16 23:16:34 +08:00
superconvert
2a953f0b1e
Create xfce4.md 2022-08-16 23:03:46 +08:00
17 changed files with 2931 additions and 863 deletions

View File

@ -1,6 +1,6 @@
#!/bin/sh
rm work/kernel_install/ work/glibc_install/ work/busybox_install/ work/libgcc_install work/binutils_install -rf
# rm work/kernel_install/ work/glibc_install/ work/busybox_install/ work/libgcc_install work/binutils_install -rf
if [ -f "/usr/bin/apt" ]; then
apt -y install gcc g++ make gawk bison libelf-dev bridge-utils qemu-system docker.io

View File

@ -1,24 +1,38 @@
#!/bin/sh
if [ -f "/usr/bin/apt" ]; then
apt -y install gcc g++ make gawk flex bison libelf-dev libssl-dev bridge-utils
fi
if [ -f "/usr/bin/yum" ]; then
yum -y install gcc gcc-c++ make gawk flex bison elfutils-libelf libssl-dev bridge-utils
fi
#-----------------------------------------------
#
# 导入公共变量
# 导入公共变量 ( xfce4 需要 5.4.0 的内核, glibc 必须为 2.27 否则 xfce4 相关的编译有问题 )
#
#-----------------------------------------------
. ./common.sh
#LINUX_SRC_URL=https://kernel.org/pub/linux/kernel/v4.x/linux-4.14.9.tar.xz
LINUX_SRC_URL=https://mirror.bjtu.edu.cn/kernel/linux/kernel/v4.x/linux-4.14.9.tar.xz
LINUX_SRC_URL=https://mirror.bjtu.edu.cn/kernel/linux/kernel/v5.x/linux-5.8.6.tar.xz
#GLIBC_SRC_URL=https://ftp.gnu.org/gnu/glibc/glibc-2.32.tar.bz2
GLIBC_SRC_URL=https://mirrors.ustc.edu.cn/gnu/glibc/glibc-2.32.tar.bz2
GLIBC_SRC_URL=https://mirrors.ustc.edu.cn/gnu/glibc/glibc-2.27.tar.xz
BUSYBOX_SRC_URL=https://busybox.net/downloads/busybox-1.34.1.tar.bz2
LSHW_SRC_URL=https://www.ezix.org/software/files/lshw-B.02.19.2.tar.gz
LSOF_SRC_URL=https://github.com/lsof-org/lsof/releases/download/4.95.0/lsof_4.95.0.linux.tar.bz2
STRACE_SRC_URL=https://github.com/strace/strace/releases/download/v5.19/strace-5.19.tar.xz
PCIUTILS_SRC_URL=http://mj.ucw.cz/download/linux/pci/pciutils-3.8.0.tar.gz
OPENSSL_SRC_URL=https://www.openssl.org/source/openssl-1.1.1q.tar.gz
OPENSSH_SRC_URL=https://cdn.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-8.8p1.tar.gz
LIBMNL_SRC_URL=https://netfilter.org/projects/libmnl/files/libmnl-1.0.5.tar.bz2
LIBNFTNL_SRC_URL=https://netfilter.org/projects/libnftnl/files/libnftnl-1.2.3.tar.bz2
IPTABLES_SRC_URL=https://www.netfilter.org/projects/iptables/files/iptables-1.8.8.tar.bz2
#GCC_SRC_URL=https://ftpmirror.gnu.org/gcc/gcc-7.5.0/gcc-7.5.0.tar.xz
GCC_SRC_URL=https://mirrors.ustc.edu.cn/gnu/gcc/gcc-7.5.0/gcc-7.5.0.tar.xz
#BINUTILS_SRC_URL=https://ftp.gnu.org/gnu/binutils/binutils-2.36.tar.xz
BINUTILS_SRC_URL=https://mirrors.ustc.edu.cn/gnu/binutils/binutils-2.36.tar.xz
export CFLAGS="-Os -s -fno-stack-protector -fomit-frame-pointer -U_FORTIFY_SOURCE"
#----------------------------------------------
#
# 下载源码
@ -26,32 +40,20 @@ export CFLAGS="-Os -s -fno-stack-protector -fomit-frame-pointer -U_FORTIFY_SOURC
#----------------------------------------------
mkdir -pv source
cd source
LINUX_SRC_NAME=$(file_name ${LINUX_SRC_URL})
if [ ! -f ${LINUX_SRC_NAME} ]; then
wget -c -t 0 $LINUX_SRC_URL
fi
GLIBC_SRC_NAME=$(file_name ${GLIBC_SRC_URL})
if [ ! -f ${GLIBC_SRC_NAME} ]; then
wget -c -t 0 $GLIBC_SRC_URL
fi
BUSYBOX_SRC_NAME=$(file_name ${BUSYBOX_SRC_URL})
if [ ! -f ${BUSYBOX_SRC_NAME} ]; then
wget -c -t 0 $BUSYBOX_SRC_URL
fi
GCC_SRC_NAME=$(file_name ${GCC_SRC_URL})
if [ ! -f ${GCC_SRC_NAME} ]; then
wget -c -t 0 $GCC_SRC_URL
fi
BINUTILS_SRC_NAME=$(file_name ${BINUTILS_SRC_URL})
if [ ! -f ${BINUTILS_SRC_NAME} ]; then
wget -c -t 0 $BINUTILS_SRC_URL
fi
LINUX_SRC_NAME=$(download_src ${LINUX_SRC_URL})
GLIBC_SRC_NAME=$(download_src ${GLIBC_SRC_URL})
BUSYBOX_SRC_NAME=$(download_src ${BUSYBOX_SRC_URL})
LSHW_SRC_NAME=$(download_src ${LSHW_SRC_URL})
LSOF_SRC_NAME=$(download_src ${LSOF_SRC_URL})
STRACE_SRC_NAME=$(download_src ${STRACE_SRC_URL})
PCIUTILS_SRC_NAME=$(download_src ${PCIUTILS_SRC_URL})
OPENSSL_SRC_NAME=$(download_src ${OPENSSL_SRC_URL})
OPENSSH_SRC_NAME=$(download_src ${OPENSSH_SRC_URL})
LIBMNL_SRC_NAME=$(download_src ${LIBMNL_SRC_URL})
LIBNFTNL_SRC_NAME=$(download_src ${LIBNFTNL_SRC_URL})
IPTABLES_SRC_NAME=$(download_src ${IPTABLES_SRC_URL})
GCC_SRC_NAME=$(download_src ${GCC_SRC_URL})
BINUTILS_SRC_NAME=$(download_src ${BINUTILS_SRC_URL})
cd ..
#---------------------------------------------
@ -60,100 +62,240 @@ cd ..
#
#---------------------------------------------
mkdir -pv ${build_dir}
LINUX_SRC_DIR=${build_dir}"/"$(file_dirname ${LINUX_SRC_NAME} .tar.xz)
if [ ! -d ${LINUX_SRC_DIR} ]; then
echo "unzip ${LINUX_SRC_NAME} source code"
tar xf source/${LINUX_SRC_NAME} -C ${build_dir}
fi
GLIBC_SRC_DIR=${build_dir}"/"$(file_dirname ${GLIBC_SRC_NAME} .tar.bz2)
if [ ! -d ${GLIBC_SRC_DIR} ]; then
echo "unzip ${GLIBC_SRC_NAME} source code"
tar xf source/${GLIBC_SRC_NAME} -C ${build_dir}
fi
BUSYBOX_SRC_DIR=${build_dir}"/"$(file_dirname ${BUSYBOX_SRC_NAME} .tar.bz2)
if [ ! -d ${BUSYBOX_SRC_DIR} ]; then
echo "unzip ${BUSYBOX_SRC_NAME} source code"
tar xf source/${BUSYBOX_SRC_NAME} -C ${build_dir}
fi
GCC_SRC_DIR=${build_dir}"/"$(file_dirname ${GCC_SRC_NAME} .tar.xz)
if [ ! -d ${GCC_SRC_DIR} ]; then
echo "unzip ${GCC_SRC_NAME} source code"
tar xf source/${GCC_SRC_NAME} -C ${build_dir}
fi
BINUTILS_SRC_DIR=${build_dir}"/"$(file_dirname ${BINUTILS_SRC_NAME} .tar.xz)
if [ ! -d ${BINUTILS_SRC_DIR} ]; then
echo "unzip ${BINUTILS_SRC_NAME} source code"
tar xf source/${BINUTILS_SRC_NAME} -C ${build_dir}
fi
LINUX_SRC_DIR=$(unzip_src ".tar.xz" ${LINUX_SRC_NAME}); echo "unzip ${LINUX_SRC_NAME} source code"
GLIBC_SRC_DIR=$(unzip_src ".tar.xz" ${GLIBC_SRC_NAME}); echo "unzip ${GLIBC_SRC_NAME} source code"
BUSYBOX_SRC_DIR=$(unzip_src ".tar.bz2" ${BUSYBOX_SRC_NAME}); echo "unzip ${BUSYBOX_SRC_NAME} source code"
LSHW_SRC_DIR=$(unzip_src ".tar.gz" ${LSHW_SRC_NAME}); echo "unzip ${LSHW_SRC_NAME} source code"
LSOF_SRC_DIR=$(unzip_src ".tar.bz2" ${LSOF_SRC_NAME}); echo "unzip ${LSOF_SRC_NAME} source code"
STRACE_SRC_DIR=$(unzip_src ".tar.xz" ${STRACE_SRC_NAME}); echo "unzip ${STRACE_SRC_NAME} source code"
PCIUTILS_SRC_DIR=$(unzip_src ".tar.gz" ${PCIUTILS_SRC_NAME}); echo "unzip ${PCIUTILS_SRC_NAME} source code"
OPENSSL_SRC_DIR=$(unzip_src ".tar.gz" ${OPENSSL_SRC_NAME}); echo "unzip ${OPENSSL_SRC_NAME} source code"
OPENSSH_SRC_DIR=$(unzip_src ".tar.gz" ${OPENSSH_SRC_NAME}); echo "unzip ${OPENSSH_SRC_NAME} source code"
LIBMNL_SRC_DIR=$(unzip_src ".tar.bz2" ${LIBMNL_SRC_NAME}); echo "unzip ${LIBMNL_SRC_NAME} source code"
LIBNFTNL_SRC_DIR=$(unzip_src ".tar.bz2" ${LIBNFTNL_SRC_NAME}); echo "unzip ${LIBNFTNL_SRC_NAME} source code"
IPTABLES_SRC_DIR=$(unzip_src ".tar.bz2" ${IPTABLES_SRC_NAME}); echo "unzip ${IPTABLES_SRC_NAME} source code"
GCC_SRC_DIR=$(unzip_src ".tar.xz" ${GCC_SRC_NAME}); echo "unzip ${GCC_SRC_NAME} source code"
BINUTILS_SRC_DIR=$(unzip_src ".tar.xz" ${BINUTILS_SRC_NAME}); echo "unzip ${BINUTILS_SRC_NAME} source code"
#-----------------------------------------------
#
# 重新生成目标文件
#
#-----------------------------------------------
if [ "$1" != "" ]; then
if [ $1 != "rebuild" ]; then
exit
fi
if [ "$1" = "rebuild" ]; then
echo "rebuild"
cd ${build_dir}
rm -rf linux_install glibc_install busybox_install gcc_install binutils_install
# 编译内核, 最终所有模块都装到目录 /lib/modules/4.14.9
if [ ! -d "linux_install" ]; then
mkdir -pv linux_install && cd ${LINUX_SRC_DIR}
make INSTALL_HDR_PATH=${linux_install} headers_install -j8 && cp arch/x86_64/boot/bzImage ${linux_install} && cd ..
fi
# 编译glibc
if [ ! -d "glibc_install" ]; then
mkdir -pv glibc_install && cd ${GLIBC_SRC_DIR}
mkdir -pv build && cd build
make install -j8 DESTDIR=${glibc_install} && cd .. && cd ..
fi
# 编译 busybox
if [ ! -d "busybox_install" ]; then
mkdir -pv busybox_install && cd ${BUSYBOX_SRC_DIR}
make CONFIG_PREFIX=${busybox_install} install && cd ..
fi
# 编译 libgcc
if [ ! -d "gcc_install" ]; then
mkdir -pv gcc_install && cd ${GCC_SRC_DIR}
make install -j8 DESTDIR=${gcc_install} && cd ..
fi
# 编译 binutils
if [ ! -d "binutils_install" ]; then
mkdir -pv binutils_install && cd ${BINUTILS_SRC_DIR}
make install -j8 DESTDIR=${binutils_install} && cd ..
fi
rm -rf linux_install glibc_install busybox_install lshw_install lsof_install pciutils_install strace_install \
openssl_install openssh_install gcc_install binutils_install
cd ..
exit
fi
#---------------------------------------------
#
# 编译源码
#
#---------------------------------------------
export CFLAGS="-Os -s -fno-stack-protector -fomit-frame-pointer -U_FORTIFY_SOURCE"
cd ${build_dir}
# 编译内核, 最终所有模块都装到目录 /lib/modules/4.14.9
# 编译内核, 最终所有模块都装到目录 /lib/modules/5.8.6
if [ ! -d "linux_install" ]; then
mkdir -pv linux_install && cd ${LINUX_SRC_DIR} && make mrproper && make x86_64_defconfig
# Enable the VESA framebuffer for graphics support.
sed -i "s/.*CONFIG_FB_VESA.*/CONFIG_FB_VESA=y/" .config
# 下面的配置主要显卡相关的配置,必须开启, 内核 3d 加速 https://wiki.gentoo.org/wiki/Xorg/Hardware_3D_acceleration_guide
# xfce4 需要 drm 支持,内核版本尽量大于等于 18.04 的,所以选取了 5.8.6 的内核
sed -i "s/# CONFIG_X86_SYSFB is not set/CONFIG_X86_SYSFB=y/" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_IRQCHIP=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_IRQFD=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_IRQ_ROUTING=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_EVENTFD=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_KVM_MMIO=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_KVM_ASYNC_PF=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_MSI=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_KVM_VFIO=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_KVM_GENERIC_DIRTYLOG_READ_PROTECT=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_KVM_COMPAT=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_IRQ_BYPASS=y" .config
sed -i "/CONFIG_VIRTUALIZATION=y/i\CONFIG_HAVE_KVM_NO_POLL=y" .config
sed -i "s/# CONFIG_KVM is not set/CONFIG_KVM=y/" .config
sed -i "/CONFIG_AS_AVX512=y/i\CONFIG_KVM_INTEL=y" .config
sed -i "/CONFIG_AS_AVX512=y/i\CONFIG_KVM_AMD=y" .config
sed -i "/CONFIG_AS_AVX512=y/i\CONFIG_KVM_MMU_AUDIT=y" .config
sed -i "/CONFIG_HAVE_IOREMAP_PROT=y/i\CONFIG_USER_RETURN_NOTIFIER=y" .config
sed -i "/CONFIG_BLK_PM=y/i\CONFIG_BLK_MQ_VIRTIO=y" .config
sed -i "/CONFIG_ASN1=y/i\CONFIG_PREEMPT_NOTIFIERS=y" .config
sed -i "/# CONFIG_MEMORY_HOTPLUG is not set/i\CONFIG_MEMORY_ISOLATION=y" .config
sed -i "/CONFIG_PHYS_ADDR_T_64BIT=y/i\CONFIG_CONTIG_ALLOC=y" .config
sed -i "s/# CONFIG_CMA is not set/CONFIG_CMA=y/" .config
sed -i "/# CONFIG_ZPOOL is not set/i\# CONFIG_CMA_DEBUG is not set" .config
sed -i "/# CONFIG_ZPOOL is not set/i\# CONFIG_CMA_DEBUGFS is not set" .config
sed -i "/# CONFIG_ZPOOL is not set/i\CONFIG_CMA_AREAS=7" .config
sed -i "/CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y/i\CONFIG_HMM_MIRROR=y" .config
sed -i "/# end of Memory Management options/i\CONFIG_MAPPING_DIRTY_HELPERS=y" .config
sed -i "/CONFIG_ALLOW_DEV_COREDUMP=y/i\CONFIG_WANT_DEV_COREDUMP=y" .config
sed -i "/# CONFIG_DEBUG_DRIVER is not set/i\CONFIG_DEV_COREDUMP=y" .config
sed -i "/# CONFIG_BLK_DEV_RBD is not set/i\# CONFIG_VIRTIO_BLK is not set" .config
sed -i "/# CONFIG_NLMON is not set/i\# CONFIG_VIRTIO_NET is not set" .config
sed -i "/# CONFIG_IPMI_HANDLER is not set/i\# CONFIG_VIRTIO_CONSOLE is not set" .config
sed -i "/# CONFIG_APPLICOM is not set/i\# CONFIG_HW_RANDOM_VIRTIO is not set" .config
sed -i "s/# CONFIG_AGP_SIS is not set/CONFIG_AGP_SIS=y/" .config
sed -i "s/# CONFIG_AGP_VIA is not set/CONFIG_AGP_VIA=y/" .config
sed -i "s/# CONFIG_DRM_DP_AUX_CHARDEV is not set/CONFIG_DRM_DP_AUX_CHARDEV=y/" .config
sed -i "s/# CONFIG_DRM_LOAD_EDID_FIRMWARE is not set/CONFIG_DRM_LOAD_EDID_FIRMWARE=y/" .config
sed -i "/# CONFIG_DRM_DP_CEC is not set/a\CONFIG_DRM_TTM=y" .config
sed -i "/CONFIG_DRM_TTM=y/a\CONFIG_DRM_TTM_DMA_PAGE_POOL=y" .config
sed -i "/CONFIG_DRM_TTM_DMA_PAGE_POOL=y/a\CONFIG_DRM_VRAM_HELPER=y" .config
sed -i "/CONFIG_DRM_VRAM_HELPER=y/a\CONFIG_DRM_TTM_HELPER=y" .config
sed -i "/CONFIG_DRM_TTM_HELPER=y/a\CONFIG_DRM_GEM_SHMEM_HELPER=y" .config
sed -i "/CONFIG_DRM_GEM_SHMEM_HELPER=y/a\CONFIG_DRM_VM=y" .config
sed -i "/CONFIG_DRM_VM=y/a\CONFIG_DRM_SCHED=y" .config
sed -i "/# CONFIG_DRM_RADEON is not set/d" .config
sed -i "/# CONFIG_DRM_AMDGPU is not set/d" .config
sed -i "/# CONFIG_DRM_NOUVEAU is not set/d" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_RADEON=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_RADEON_USERPTR=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMDGPU=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMDGPU_SI=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMDGPU_CIK=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMDGPU_USERPTR=y" .config
sed -i "/CONFIG_DRM_I915=y/i\# CONFIG_DRM_AMDGPU_GART_DEBUGFS is not set\n" .config
sed -i "/CONFIG_DRM_I915=y/i\#\n# ACP (Audio CoProcessor) Configuration\n#" .config
sed -i "/CONFIG_DRM_I915=y/i\# CONFIG_DRM_AMD_ACP is not set" .config
sed -i "/CONFIG_DRM_I915=y/i\# end of ACP (Audio CoProcessor) Configuration\n" .config
sed -i "/CONFIG_DRM_I915=y/i\#\n# Display Engine Configuration\n#" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMD_DC=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_AMD_DC_DCN=y" .config
sed -i "/CONFIG_DRM_I915=y/i\# CONFIG_DRM_AMD_DC_HDCP is not set" .config
sed -i "/CONFIG_DRM_I915=y/i\# CONFIG_DEBUG_KERNEL_DC is not set" .config
sed -i "/CONFIG_DRM_I915=y/i\# end of Display Engine Configuration\n" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_HSA_AMD=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_NOUVEAU=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT=y" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_NOUVEAU_DEBUG=5" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_NOUVEAU_DEBUG_DEFAULT=3" .config
sed -i "/CONFIG_DRM_I915=y/i\# CONFIG_NOUVEAU_DEBUG_MMU is not set" .config
sed -i "/CONFIG_DRM_I915=y/i\CONFIG_DRM_NOUVEAU_BACKLIGHT=y" .config
sed -i "s/# CONFIG_DRM_I915_GVT is not set/CONFIG_DRM_I915_GVT=y/" .config
sed -i "s/# CONFIG_DRM_VGEM is not set/CONFIG_DRM_VGEM=y/" .config
sed -i "s/# CONFIG_DRM_VKMS is not set/CONFIG_DRM_VKMS=y/" .config
sed -i "s/# CONFIG_DRM_VMWGFX is not set/CONFIG_DRM_VMWGFX=y\nCONFIG_DRM_VMWGFX_FBCON=y/" .config
sed -i "s/# CONFIG_DRM_GMA500 is not set/CONFIG_DRM_GMA500=y\nCONFIG_DRM_GMA600=y\nCONFIG_DRM_GMA3600=y/" .config
sed -i "s/# CONFIG_DRM_MGAG200 is not set/CONFIG_DRM_MGAG200=y/" .config
sed -i "s/# CONFIG_DRM_QXL is not set/CONFIG_DRM_QXL=y/" .config
sed -i "s/# CONFIG_DRM_BOCHS is not set/CONFIG_DRM_BOCHS=y\n# CONFIG_DRM_VIRTIO_GPU is not set/" .config
sed -i "s/# CONFIG_DRM_VIRTIO_GPU is not set/CONFIG_DRM_VIRTIO_GPU=y/" .config
sed -i "s/# CONFIG_DRM_ETNAVIV is not set/CONFIG_DRM_ETNAVIV=y\nCONFIG_DRM_ETNAVIV_THERMAL=y/" .config
sed -i "s/# CONFIG_DRM_CIRRUS_QEMU is not set/CONFIG_DRM_CIRRUS_QEMU=y/" .config
sed -i "s/# CONFIG_DRM_GM12U320 is not set/CONFIG_DRM_GM12U320=y/" .config
sed -i "s/# CONFIG_DRM_VBOXVIDEO is not set/CONFIG_DRM_VBOXVIDEO=y/" .config
sed -i "s/# CONFIG_DRM_LEGACY is not set/CONFIG_DRM_LEGACY=y/" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_TDFX is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_R128 is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_I810 is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_MGA is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_SIS is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_VIA is not set" .config
sed -i "/CONFIG_DRM_PANEL_ORIENTATION_QUIRKS=y/i\# CONFIG_DRM_SAVAGE is not set" .config
sed -i "s/# CONFIG_FIRMWARE_EDID is not set/CONFIG_FIRMWARE_EDID=y\nCONFIG_FB_DDC=y\nCONFIG_FB_BOOT_VESA_SUPPORT=y/" .config
sed -i "/CONFIG_FB_MODE_HELPERS=y/i\CONFIG_FB_SVGALIB=y" .config
sed -i "/CONFIG_FB_MODE_HELPERS=y/i\CONFIG_FB_BACKLIGHT=y" .config
sed -i "s/# CONFIG_FB_CIRRUS is not set/CONFIG_FB_CIRRUS=y/" .config
sed -i "s/# CONFIG_FB_VGA16 is not set/CONFIG_FB_VGA16=y/" .config
sed -i "s/# CONFIG_FB_UVESA is not set/CONFIG_FB_UVESA=y/" .config
sed -i "s/# CONFIG_FB_VESA is not set/CONFIG_FB_VESA=y/" .config
sed -i "s/# CONFIG_FB_OPENCORES is not set/CONFIG_FB_OPENCORES=y/" .config
sed -i "s/# CONFIG_FB_NVIDIA is not set/CONFIG_FB_NVIDIA=y\nCONFIG_FB_NVIDIA_I2C=y\nCONFIG_FB_NVIDIA_DEBUG=y\nCONFIG_FB_NVIDIA_BACKLIGHT=y/" .config
sed -i "s/# CONFIG_FB_RIVA is not set/CONFIG_FB_RIVA=y\n# CONFIG_FB_RIVA_I2C is not set\n# CONFIG_FB_RIVA_DEBUG is not set\nCONFIG_FB_RIVA_BACKLIGHT=y/" .config
sed -i "s/# CONFIG_FB_I740 is not set/CONFIG_FB_I740=y/" .config
sed -i "s/# CONFIG_FB_RADEON is not set/CONFIG_FB_RADEON=y\nCONFIG_FB_RADEON_I2C=y\nCONFIG_FB_RADEON_BACKLIGHT=y\n# CONFIG_FB_RADEON_DEBUG is not set/" .config
sed -i "s/# CONFIG_FB_3DFX is not set/CONFIG_FB_3DFX=y\nCONFIG_FB_3DFX_ACCEL=y\nCONFIG_FB_3DFX_I2C=y/" .config
sed -i "s/# CONFIG_FB_VOODOO1 is not set/CONFIG_FB_VOODOO1=y/" .config
sed -i "s/# CONFIG_FB_VT8623 is not set/CONFIG_FB_VT8623=y/" .config
sed -i "s/# CONFIG_FB_TRIDENT is not set/CONFIG_FB_TRIDENT=y/" .config
sed -i "s/# CONFIG_FB_IBM_GXT4500 is not set/CONFIG_FB_IBM_GXT4500=y/" .config
sed -i "s/# CONFIG_FB_SIMPLE is not set/CONFIG_FB_SIMPLE=y/" .config
sed -i "/CONFIG_HDMI=y/i\CONFIG_VGASTATE=y" .config
sed -i "/# CONFIG_VIRT_DRIVERS is not set/i\CONFIG_IRQ_BYPASS_MANAGER=y" .config
sed -i "/CONFIG_VIRTIO_MENU=y/i\CONFIG_VIRTIO=y" .config
sed -i "s/# CONFIG_VIRTIO_PCI is not set/CONFIG_VIRTIO_PCI=y\nCONFIG_VIRTIO_PCI_LEGACY=y\n# CONFIG_VIRTIO_BALLOON is not set\n# CONFIG_VIRTIO_INPUT is not set/" .config
sed -i "s/# CONFIG_ACPI_WMI is not set/CONFIG_ACPI_WMI=y/" .config
sed -i "/# CONFIG_ACERHDF is not set/i\CONFIG_WMI_BMOF=y" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_ALIENWARE_WMI is not set" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_HUAWEI_WMI is not set" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_INTEL_WMI_SBL_FW_UPDATE is not set" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_INTEL_WMI_THUNDERBOLT is not set" .config
sed -i "/# CONFIG_ACERHDF is not set/i\CONFIG_MXM_WMI=y" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_PEAQ_WMI is not set" .config
sed -i "/# CONFIG_ACERHDF is not set/i\# CONFIG_XIAOMI_WMI is not set" .config
sed -i "/# CONFIG_APPLE_GMUX is not set/i\# CONFIG_ACER_WMI is not set" .config
sed -i "/CONFIG_EEEPC_LAPTOP=y/i\# CONFIG_ASUS_WMI is not set" .config
sed -i "/# CONFIG_AMILO_RFKILL is not set/i\# CONFIG_DELL_WMI_AIO is not set" .config
sed -i "/# CONFIG_AMILO_RFKILL is not set/i\# CONFIG_DELL_WMI_LED is not set" .config
sed -i "/# CONFIG_IBM_RTL is not set/i\# CONFIG_HP_WMI is not set" .config
sed -i "/# CONFIG_SAMSUNG_LAPTOP is not set/i\# CONFIG_MSI_WMI is not set" .config
sed -i "/# CONFIG_ACPI_CMPC is not set/i\# CONFIG_TOSHIBA_WMI is not set" .config
sed -i "/# CONFIG_PANASONIC_LAPTOP is not set/i\# CONFIG_LG_LAPTOP is not set" .config
sed -i "/# CONFIG_CRYPTO_TEST is not set/a\CONFIG_CRYPTO_ENGINE=m" .config
sed -i "/# CONFIG_CRYPTO_DEV_SAFEXCEL is not set/i\CONFIG_CRYPTO_DEV_VIRTIO=m" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\CONFIG_DMA_CMA=y\n" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\#\n# Default contiguous memory area size:\n#" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\CONFIG_CMA_SIZE_MBYTES=0" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\CONFIG_CMA_SIZE_SEL_MBYTES=y" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\# CONFIG_CMA_SIZE_SEL_MIN is not set" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\# CONFIG_CMA_SIZE_SEL_MAX is not set" .config
sed -i "/# CONFIG_DMA_API_DEBUG is not set/i\CONFIG_CMA_ALIGNMENT=8" .config
# 鼠标的配置 ( 否则 xfce4 界面上鼠标不能操作 /dev/input/mice, 上层需要 xf86-input-evdev, libevdev )
sed -i "/# CONFIG_INPUT_MOUSEDEV is not set/a\CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768" .config
sed -i "/# CONFIG_INPUT_MOUSEDEV is not set/a\CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024" .config
sed -i "/# CONFIG_INPUT_MOUSEDEV is not set/a\CONFIG_INPUT_MOUSEDEV_PSAUX=y" .config
sed -i "s/# CONFIG_INPUT_MOUSEDEV is not set/CONFIG_INPUT_MOUSEDEV=y/" .config
sed -i "s/# CONFIG_UHID is not set/CONFIG_UHID=y/" .config
sed -i "s/# CONFIG_USB_DYNAMIC_MINORS is not set/CONFIG_USB_DYNAMIC_MINORS=y/" .config
sed -i "s/# CONFIG_USB_XHCI_PLATFORM is not set/CONFIG_USB_XHCI_PLATFORM=y/" .config
sed -i "s/# CONFIG_USB_EHCI_ROOT_HUB_TT is not set/CONFIG_USB_EHCI_ROOT_HUB_TT=y/" .config
sed -i "s/# CONFIG_USB_EHCI_HCD_PLATFORM is not set/CONFIG_USB_EHCI_HCD_PLATFORM=y/" .config
sed -i "s/# CONFIG_USB_OHCI_HCD_PLATFORM is not set/CONFIG_USB_OHCI_HCD_PLATFORM=y/" .config
# 键盘驱动 ( libevdev https://linuxfromscratch.org/blfs/view/11.0/x/x7driver.html )
sed -i "s/# CONFIG_INPUT_UINPUT is not set/CONFIG_INPUT_UINPUT=y/" .config
# wacom 驱动支持 ( xf86-input-wacom )
sed -i "s/# CONFIG_HID_WACOM is not set/CONFIG_HID_WACOM=y/" .config
# 网络需要 TUN/TAP 驱动 [ Device Drivers ] ---> [ Network device support ] ---> [ Universal TUN/TAP device driver support ]
make bzImage -j8
#cd linux-4.14.9 && make x86_64_defconfig && make bzImage -j8 && make modules && make modules_install && cd ..
make INSTALL_HDR_PATH=${linux_install} headers_install -j8 && cp arch/x86_64/boot/bzImage ${linux_install} && cd ..
make modules -j8
#cd linux-5.8.6 && make x86_64_defconfig && make bzImage -j8 && make modules && make modules_install && cd ..
make INSTALL_HDR_PATH=${linux_install} headers_install -j8
make modules_install INSTALL_MOD_PATH=${linux_install} -j8 && cp arch/x86_64/boot/bzImage ${linux_install} || exit
cd ..
fi
# 编译glibc
@ -167,43 +309,174 @@ if [ ! -d "glibc_install" ]; then
--disable-werror \
--disable-werror \
CFLAGS="$CFLAGS"
make -j8 && make install -j8 DESTDIR=${glibc_install} && cd .. && cd ..
make -j8 && make install -j8 DESTDIR=${glibc_install} || exit
cd .. && cd ..
fi
# 编译 busybox
if [ ! -d "busybox_install" ]; then
mkdir -pv busybox_install && cd ${BUSYBOX_SRC_DIR} && make distclean && make defconfig
# 屏蔽掉 lsof 这个自带的太简单
sed -i "s/CONFIG_LSOF=y/# CONFIG_LSOF is not set/" .config
# 屏蔽掉 lspci 这个自带的太简单
sed -i "s/CONFIG_LSPCI=y/# CONFIG_LSPCI is not set/" .config
# 静态编译 sed -i "s/# CONFIG_STATIC is not set/CONFIG_STATIC=y/g" .config
sed -i "s|.*CONFIG_SYSROOT.*|CONFIG_SYSROOT=\"${glibc_install}\"|" .config
sed -i "s|.*CONFIG_EXTRA_CFLAGS.*|CONFIG_EXTRA_CFLAGS=\"-I${linux_install}/include -I${glibc_install}/include -L${glibc_install}/usr/lib64 $CFLAGS\"|" .config
make busybox -j8 && make CONFIG_PREFIX=${busybox_install} install && cd ..
# 环境变量 PATH 的设定,因为 busybox 的 init 会覆盖用户设置的 PATH只能源码进行编译
sed -i "s|#define BB_ADDITIONAL_PATH \"\"|#define BB_ADDITIONAL_PATH \":/usr/local/sbin:/usr/local/bin\"|" include/libbb.h
make busybox -j8 && make CONFIG_PREFIX=${busybox_install} install || exit
cd ..
fi
# 编译 gcc
if [ ! -d "gcc_install" ]; then
mkdir -pv gcc_install && cd ${GCC_SRC_DIR} && make distclean && rm ./config.cache
./contrib/download_prerequisites
./configure --prefix=/usr --enable-languages=c,c++ --disable-multilib --disable-static --disable-libquadmath --enable-shared
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${gcc_install} && cd ..
#------------------------------------------------------------------
# 编译通用工具
#------------------------------------------------------------------
if [ "${with_util}" = true ]; then
# 编译 lshw ( 调试方便 )
if [ ! -d "lshw_install" ]; then
mkdir -pv lshw_install && cd ${LSHW_SRC_DIR}
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${lshw_install} PREFIX=/usr || exit
cd ..
fi
# 编译 pciutils ( busybox 的 lspci 太简单 )
if [ ! -d "pciutils_install" ]; then
mkdir -pv pciutils_install && cd ${PCIUTILS_SRC_DIR}
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${pciutils_install} PREFIX=/usr || exit
cd ..
fi
# 编译 lsof ( busybox 的太简单 )
if [ ! -d "lsof_install" ]; then
mkdir -pv lsof_install && cd ${LSOF_SRC_DIR}
./Configure linux -n
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && mkdir -pv ${lsof_install}/usr/bin && cp ./lsof ${lsof_install}/usr/bin || exit
cd ..
fi
# 编译 strace ( 方便调试 )
if [ ! -d "strace_install" ]; then
mkdir -pv strace_install && cd ${STRACE_SRC_DIR}
./configure --prefix=/usr --enable-mpers=no
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${strace_install} PREFIX=/usr || exit
cd ..
fi
fi
# 编译 binutils
if [ ! -d "binutils_install" ]; then
mkdir -pv binutils_install && cd ${BINUTILS_SRC_DIR} && make distclean
./configure --prefix=/usr
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${binutils_install} && cd ..
#------------------------------------------------------------------
# 编译 openssh
#------------------------------------------------------------------
if [ "${with_ssh}" = true ]; then
# 编译 openssl
if [ ! -d "openssl_install" ]; then
mkdir -pv openssl_install && cd ${OPENSSL_SRC_DIR}
./config --prefix=/usr shared
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${openssl_install} PREFIX=/usr || exit
cd ..
fi
# 编译 openssh ( 需要 openssl )
if [ ! -d "openssh_install" ]; then
mkdir -pv openssh_install && cd ${OPENSSH_SRC_DIR}
./configure --prefix=/usr --sysconfdir=/etc/ssh --with-ssl-dir=${openssl_install}/usr/ --without-openssl-header-check
CFLAGS="-L${glibc_install}/lib64 -L${openssl_install}/usr/lib $CFLAGS" make -j8 && make install -j8 DESTDIR=${openssh_install} PREFIX=/usr
# 修改配置文件
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/" ${openssh_install}/etc/ssh/sshd_config
echo "HostKeyAlgorithms=ssh-rsa,ssh-dss" >> ${openssh_install}/etc/ssh/sshd_config
echo "KexAlgorithms=diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" >> ${openssh_install}/etc/ssh/sshd_config
# 准备环境
if [ ! -d "${openssh_install}/var/empty" ]; then
mkdir -pv ${openssh_install}/var/empty
fi
chmod 744 ${openssh_install}/var/empty/
chown root ${openssh_install}/var/empty/
if [ ! -f "${openssh_install}/etc/ssh/ssh_host_dsa_key" ]; then
ssh-keygen -t dsa -P "" -f ${openssh_install}/etc/ssh/ssh_host_dsa_key
fi
if [ ! -f "${openssh_install}/etc/ssh/ssh_host_rsa_key" ]; then
ssh-keygen -t rsa -P "" -f ${openssh_install}/etc/ssh/ssh_host_rsa_key
fi
# 开启 sftp, 可以进行文件上传
if [ -f "${openssh_install}/etc/ssh/sshd_config" ]; then
sed -i "s/\/usr\/libexec\/sftp-server/internal-sftp/" ${openssh_install}/etc/ssh/sshd_config
fi
cd ..
fi
fi
#------------------------------------------------------------------
# 编译防火墙
#------------------------------------------------------------------
if [ "${with_ufw}" = true ]; then
ufw_include=" \
-I${libmnl_install}/usr/include \
-I${libnftnl_install}/usr/include"
ufw_library=" \
-L${libmnl_install}/usr/lib -lmnl \
-L${libnftnl_install}/usr/lib -lnftnl"
# 编译 libmnl
if [ ! -d "libmnl_install" ]; then
mkdir -pv libmnl_install && cd ${LIBMNL_SRC_DIR}
./configure --prefix=/usr
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${libmnl_install} PREFIX=/usr || exit
cd ..
fi
# 编译 libnftnl
if [ ! -d "libnftnl_install" ]; then
mkdir -pv libnftnl_install && cd ${LIBNFTNL_SRC_DIR}
export LIBMNL_CFLAGS="-I${libmnl_install}/usr/include"
export LIBMNL_LIBS="-L${libmnl_install}/usr/lib -lmnl"
./configure --prefix=/usr
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${libnftnl_install} PREFIX=/usr || exit
cd ..
fi
# 编译 iptables ( 需要 libmnl, libnftnl )
if [ ! -d "iptables_install" ]; then
mkdir -pv iptables_install && cd ${IPTABLES_SRC_DIR}
export libmnl_CFLAGS="-I${libmnl_install}/usr/include"
export libmnl_LIBS="-L${libmnl_install}/usr/lib -lmnl"
export libnftnl_CFLAGS="-I${libnftnl_install}/usr/include"
export libnftnl_LIBS="-L${libnftnl_install}/usr/lib -lnftnl"
./configure --prefix=/usr
CFLAGS="-L${glibc_install}/lib64 ${ufw_include} $CFLAGS" make -j8 && make install -j8 DESTDIR=${iptables_install} PREFIX=/usr || exit
cd ..
fi
fi
#------------------------------------------------------------------
# 编译 gcc ( xfce 需要开启这个 )
#------------------------------------------------------------------
if [ "${with_gcc}" = true ]; then
# 编译 gcc
if [ ! -d "gcc_install" ]; then
mkdir -pv gcc_install && cd ${GCC_SRC_DIR}
if [ -f "config.cache" ]; then
rm ./config.cache
fi
./contrib/download_prerequisites
./configure --prefix=/usr --enable-languages=c,c++ --disable-multilib --disable-static --disable-libquadmath --enable-shared
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${gcc_install} && cd ..
fi
# 编译 binutils
if [ ! -d "binutils_install" ]; then
mkdir -pv binutils_install && cd ${BINUTILS_SRC_DIR} && make distclean
./configure --prefix=/usr
CFLAGS="-L${glibc_install}/lib64 $CFLAGS" make -j8 && make install -j8 DESTDIR=${binutils_install} || exit
cd ..
fi
fi
cd ..
# 编译 xorg [ no same time with xfce ]
if [ "${with_xorg}" = true ]; then
./mk_xorg.sh
fi
# 编译 xfce [ no same time with xorg ]
if [ "${with_xfce}" = true ]; then
./mk_xfce.sh
# 编译 xfce ( 需要 gcc 的支持 )
if [ "${with_xfce}" = true ] && [ "${with_gcc}" = true ]; then
./mk_xfce.sh img
fi
echo "Run the next script: 02_build_img.sh"

View File

@ -1,6 +1,10 @@
#!/bin/sh
#----------------------------------------------
#
# 导入公共环境
#
#----------------------------------------------
. ./common.sh
#----------------------------------------------
@ -16,21 +20,12 @@
#
#----------------------------------------------
echo "${CYAN}--- build disk --- ${NC}"
# 创建磁盘 64M
# 创建磁盘 128M 或 256M
if [ "${with_gcc}" = false ]; then
dd if=/dev/zero of=disk.img bs=1M count=128
create_disk disk.img 4096
else
dd if=/dev/zero of=disk.img bs=1M count=256
create_disk disk.img 4096
fi
# 对磁盘进行分区一个主分区
fdisk disk.img << EOF
n
p
w
EOF
echo "${GREEN}+++ build disk ok +++${NC}"
# 磁盘镜像挂载到具体设备
@ -40,6 +35,7 @@ losetup -o 1048576 ${loop_dev} disk.img
# 对磁盘进行格式化
mkfs.ext3 ${loop_dev}
# 如果制作的 disk.img
diskfs="diskfs"
# 挂载磁盘到本地目录
mkdir -pv ${diskfs}
@ -49,7 +45,7 @@ grub-install --boot-directory=${diskfs}/boot/ --target=i386-pc --modules=part_ms
#---------------------------------------------
#
# 制作内核和 rootfs
# 制作内核和 rootfs ( run 目录下 udev 被服务 udevd 使用,否则 xfce 鼠标不能使用 )
#
#---------------------------------------------
rm -rf rootfs
@ -58,16 +54,19 @@ mkdir -pv rootfs/dev
mkdir -pv rootfs/etc
mkdir -pv rootfs/sys
mkdir -pv rootfs/mnt
mkdir -pv rootfs/run
mkdir -pv rootfs/tmp
mkdir -pv rootfs/lib
mkdir -pv rootfs/sbin
mkdir -pv rootfs/proc
mkdir -pv rootfs/root
mkdir -pv rootfs/lib64
mkdir -pv rootfs/var/run
mkdir -pv rootfs/lib/modules
# 拷贝内核镜像
cp ${linux_install}/bzImage ${diskfs}/boot/bzImage
cp ${linux_install}/lib ${diskfs}/ -r
# 拷贝 glibc 到 rootfs
cp ${glibc_install}/* rootfs/ -r
@ -75,11 +74,11 @@ rm -rf rootfs/var/db
rm -rf rootfs/share
rm -rf rootfs/usr/share
find rootfs/ -name "*.a" -exec rm -rf {} \;
# 编译的镜像带有 gcc 编译器
if [ "${with_gcc}" = false ]; then
rm -rf rootfs/usr/include
else
echo "${RED} with-gcc tools --- you can build your world${NC}"
cp ${glibc_install}/usr/lib64/libc_nonshared.a rootfs/usr/lib64
fi
@ -103,22 +102,30 @@ echo "${CYAN}--- build initrd ---${NC}"
# 这种方法也可以 mkinitramfs -k -o ./${diskfs}/boot/initrd 4.14.9
# 利用 Busybox 采用脚本制作 init 脚本 https://blog.csdn.net/embeddedman/article/details/7721926
# 光驱挂载 : /dev/cdrom 是 /dev/sr0 的软连接,也就是说 /dev/sr0 才是实际意义上的光驱。所以没有软连接,
# 照样可以挂载光驱。使用命令"mount /dev/sr0 /mnt/cdrom"便可以实现挂载。
make_init() {
cat<<"EOF">init
#!/bin/sh
# 必须首先挂载,否则 mdev 不能正常工作
mount -t sysfs sysfs /sys
mount -t proc proc /proc
mount -t devtmpfs udev /dev
mount -t tmpfs tmpfs /tmp -o mode=1777
# 必须挂载一下,否则下面的 mount 不上
mdev -s
mount -t ext3 /dev/sda1 /mnt
# 关闭内核烦人的输出信息
echo 0 > /proc/sys/kernel/printk
# 热插拔处理都交给 mdev
echo /sbin/mdev > /proc/sys/kernel/hotplug
# echo /sbin/mdev > /proc/sys/kernel/hotplug
echo -e "\n\e[0;32mBoot took $(cut -d' ' -f1 /proc/uptime) seconds\e[0m"
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
@ -127,7 +134,11 @@ mount --move /dev /mnt/dev
mount --move /sys /mnt/sys
mount --move /proc /mnt/proc
mount --move /tmp /mnt/tmp
# 切换到真正的磁盘系统上 rootfs ---> diskfs
# 因为 busybox 的 init 会重置环境变量 PATH 等,因此需要放到这里加载
export LD_LIBRARY_PATH="/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:/usr/lib/x86_64-linux-gnu"
# 切换到真正的磁盘系统上 rootfs ---> diskfs 切换到真正的文件系统
exec switch_root /mnt /sbin/init
EOF
@ -148,21 +159,60 @@ make_init
# 指定了利用 /etc/init.d/rcS 启动
cat<<"EOF">etc/inittab
# 启动 syslogd ( 日志系统 )
::sysinit:/bin/echo "starting syslogd ... ..."
::sysinit:/sbin/syslogd
::sysinit:/sbin/klogd
# 启动 udevd 服务,保证鼠标设备能正常监视,否则桌面系统下键盘不能使用
::sysinit:/bin/echo "starting udevd ... ..."
::sysinit:/usr/sbin/udevd --daemon
::sysinit:/usr/sbin/udevadm trigger
::sysinit:/usr/sbin/udevadm settle
# 基本启动信息都放到这个脚本里
::sysinit:echo "sysinit ++++++++++++++++++++++++++++++++++++++"
::sysinit:/etc/init.d/rcS
::sysinit:echo "sysinit ++++++++++++++++++++++++++++++++++++++"
# /bin/sh invocations on selected ttys
#
# Note below that we prefix the shell commands with a "-" to indicate to the
# shell that it is supposed to be a login shell. Normally this is handled by
# login, but since we are bypassing login in this case, BusyBox lets you do
# this yourself...
#
# Start an "askfirst" shell on the console (whatever that may be) -f root 自动登录
# 一定要加 tty1 ,否则登录时,会提示 : root login on 'UNKNOWN'
tty1::respawn:-/bin/login -f root
# Start an "askfirst" shell on /dev/tty2-4
tty2::respawn:-/bin/sh
tty3::respawn:-/bin/sh
tty4::respawn:-/bin/sh
# /sbin/getty invocations for selected ttys
tty4::respawn:/sbin/getty 38400 tty5
tty5::respawn:/sbin/getty 38400 tty6
# Example of how to put a getty on a serial line (for a terminal)
#::respawn:/sbin/getty -L ttyS0 9600 vt100
#::respawn:/sbin/getty -L ttyS1 9600 vt100
#
# Example how to put a getty on a modem line.
#::respawn:/sbin/getty 57600 ttyS2
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
::sysinit:echo "sysinit 1++++++++++++++++++++++++++++++++++++++"
::sysinit:/etc/init.d/rcS
::sysinit:echo "sysinit 2++++++++++++++++++++++++++++++++++++++"
tty1::once:echo "hello smart-os tty1"
tty1::respawn:/bin/sh
tty2::once:echo "hello smart-os tty2"
tty2::respawn:/bin/sh
tty3::once:echo "hello smart-os tty3"
tty3::respawn:/bin/sh
EOF
# 制作 initrd 文件系统
find . | cpio -R root:root -H newc -o | gzip -9 > ../${diskfs}/boot/initrd
echo "${GREEN}+++ build initrd ok +++${NC}"
cd ..
@ -174,9 +224,47 @@ cd ..
#--------------------------------------------------------------
echo "${CYAN}--- build diskfs ---${NC}"
cp rootfs/* ${diskfs} -r
# 带有 gcc 编译器
# +++ 通用工具 +++
if [ "${with_util}" = true ]; then
echo "${RED} ... build with-util${NC}"
# 单独的 lshw
cp ${lshw_install}/* ${diskfs} -r
# 单独的 lsof
cp ${lsof_install}/* ${diskfs} -r
# 单独的 pciutils
cp ${pciutils_install}/* ${diskfs} -r
if [ -f "${diskfs}/usr/share/pci.ids.gz" ]; then
mkdir -pv ${diskfs}/usr/local/share
mv ${diskfs}/usr/share/pci.ids.gz ${diskfs}/usr/local/share/pci.ids.gz
fi
# 单独的 strace
cp ${strace_install}/* ${diskfs} -r
fi
# +++ ufw +++
if [ "${with_ufw}" = true ]; then
echo "${RED} ... build with-ufw${NC}"
# 拷贝 libmnl
cp ${libmnl_install}/* ${diskfs} -r
# 拷贝 libnftnl
cp ${libnftnl_install}/* ${diskfs} -r
# 拷贝 iptables
cp ${iptables_install}/* ${diskfs} -r
fi
# +++ openssh +++
if [ "${with_ssh}" = true ]; then
echo "${RED} ... build with-ssh${NC}"
# 带有 openssl
cp ${openssl_install}/* ${diskfs} -r
# 带有 openssh
cp ${openssh_install}/* ${diskfs} -r
fi
# +++ gcc +++
if [ "${with_gcc}" = true ]; then
echo "${RED} with-gcc tools --- you can build your world${NC}"
echo "${RED} ... build with-gcc${NC}"
cp ${gcc_install}/* ${diskfs} -r
cp ${binutils_install}/usr/x86_64-pc-linux-gnu/* ${diskfs} -r
fi
@ -184,21 +272,106 @@ rm -rf ${diskfs}/init ${diskfs}/lost+found
# 测试用户登陆模式: root/123456
if [ "${with_login}" = true ]; then
echo "${RED} with-login --- it's an exciting time ${NC}"
echo "${RED} ... build with-login${NC}"
./mk_login.sh ${diskfs}
fi
# +++ xfce desktop +++
if [ "${with_xfce}" = true ]; then
echo "${RED} ... build xfce desktop${NC}"
# 构建 Xorg 的键盘数据
rm ${xfce_install}/usr/local/share/X11/xkb -rf
ln -s /usr/share/X11/xkb ${xfce_install}/usr/local/share/X11
# 依赖版本 libpcre.so.3
if [ -f "${xfce_install}/usr/local/lib/libpcre.so.1" ]; then
cp ${xfce_install}/usr/local/lib/libpcre.so.1 ${xfce_install}/usr/local/lib/libpcre.so.3
fi
# 依赖版本 libedit2
if [ -f "${xfce_install}/usr/local/lib/libedit.so.0" ]; then
cp ${xfce_install}/usr/local/lib/libedit.so.0 ${xfce_install}/usr/local/lib/libedit.so.2
fi
# 依赖版本 libtinfo.so.5
if [ -f "${xfce_install}/usr/lib/libtinfo.so.6" ]; then
cp ${xfce_install}/usr/lib/libtinfo.so.6 ${xfce_install}/usr/lib/libtinfo.so.5
fi
# 依赖版本 libffi.so.6
if [ -f "${xfce_install}/usr/local/lib/libffi.so.8" ]; then
cp ${xfce_install}/usr/local/lib/libffi.so.8 ${xfce_install}/usr/local/lib/libffi.so.6
fi
# dbus 用户添加
echo "video:x:44:" >> ${diskfs}/etc/group
echo "messagebus:x:107:" >> ${diskfs}/etc/group
echo "messagebus:x:103:107::/nonexistent:/usr/sbin/nologin" >> ${diskfs}/etc/passwd
# dbus 启动需要这个,否则 upowerd 就不能正常工作
cp ${xfce_install}/usr/share/dbus-1/* ${xfce_install}/usr/local/share/dbus-1/ -r
# dbus 启动脚本
# dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
# dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
# dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-address 3
# 常用的 dbus 命令
# 列出所有的dbus服务 :
# dbus-send --system --print-reply --dest=org.freedesktop.DBus /org/freedesktop/DBus org.freedesktop.DBus.ListActivatableNames
# UPower 的dbus服务 :
# dbus-send --print-reply --system --dest=org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower.EnumerateDevices
# 产生 xfce 启动脚本,进入系统后,手工执行这个就能拉起桌面
echo "if [ -f "/swapfile" ]; then" > ${diskfs}/xfce.sh
echo " dd if=/dev/zero of=/swapfile bs=1M count=2048" >> ${diskfs}/xfce.sh
echo " mkswap /swapfile" >> ${diskfs}/xfce.sh
echo "fi" >> ${diskfs}/xfce.sh
echo "swapon /swapfile" >> ${diskfs}/xfce.sh
echo "/usr/libexec/upowerd &" >> ${diskfs}/xinitrc
echo "/usr/local/bin/xfce4-session" >> ${diskfs}/xinitrc
echo "dbus-daemon --system --nopidfile --systemd-activation" >> ${diskfs}/xfce.sh
echo "xinit /xinitrc -- /usr/local/bin/Xorg :10" >> ${diskfs}/xfce.sh
chmod +x ${diskfs}/xfce.sh ${diskfs}/xinitrc
# 添加 machine-id
mkdir -p ${diskfs}/usr/local/var/lib/dbus
echo "2add25d2f5994832ba171755bc21f9fe" > ${diskfs}/etc/machine-id
echo "2add25d2f5994832ba171755bc21f9fe" > ${diskfs}/usr/local/var/lib/dbus/machine-id
# 这些本来需要编译完成,目前暂且拷贝
# cp /usr/lib/x86_64-linux-gnu/libLLVM-10.so.1 build/xfce_install/usr/lib/x86_64-linux-gnu/
# 拷贝 xfce4 到镜像目录,删除 .a 文件减少体积,其实编译选型不编译文档和测试代码会更小
find ${xfce_install}/ -name "*.a" -exec rm -rf {} \;
find ${xfce_install}/ -name "man" -exec rm -rf {} \;
find ${xfce_install}/ -name "*doc" -exec rm -rf {} \;
cp ${xfce_install}/* ${diskfs} -r -n
# 删除冗余文件,防止后续编译很多警告
# 依赖版本 libpcre.so.3
if [ -f "${xfce_install}/usr/local/lib/libpcre.so.1" ]; then
rm ${xfce_install}/usr/local/lib/libpcre.so.3 -rf
fi
# 依赖版本 libedit2
if [ -f "${xfce_install}/usr/local/lib/libedit.so.0" ]; then
rm ${xfce_install}/usr/local/lib/libedit.so.2 -rf
fi
# 依赖版本 libtinfo.so.5
if [ -f "${xfce_install}/usr/lib/libtinfo.so.6" ]; then
rm ${xfce_install}/usr/lib/libtinfo.so.5 -rf
fi
# 依赖版本 libffi.so.6
if [ -f "${xfce_install}/usr/local/lib/libffi.so.8" ]; then
rm ${xfce_install}/usr/local/lib/libffi.so.6 -rf
fi
fi
# 我们测试驱动, 制作的镜像启动后,我们进入此目录 insmod hello_world.ko 即可
./mk_drv.sh $(pwd)/${diskfs}/lib/modules
# 编译网卡驱动 ( 目前版本内核已集成 e1000 )
# cd ${build_dir}/linux-4.14.9 && make M=drivers/net/ethernet/intel/e1000/ && cd ../..
# cd ${build_dir}/linux-5.8.6 && make M=drivers/net/ethernet/intel/e1000/ && cd ../..
# 生成 grub.cfg 文件, 增加 console=ttyS0 就会让 qemu 输出日志到 qemu.log
# 生成 grub.cfg 文件, 增加 console=ttyS0 就会让 qemu 输出日志到 qemu.log, quiet 屏蔽内核过多的信息输出
cat - > ${diskfs}/boot/grub/grub.cfg << EOF
set timeout=3
menuentry "smart-os" {
root=(hd0,msdos1)
linux /boot/bzImage console=tty0
linux /boot/bzImage console=tty0 quiet
initrd /boot/initrd
}
EOF
@ -209,6 +382,7 @@ nameserver 8.8.8.8
nameserver 114.114.114.114
EOF
# 生成 /etc/fstab 挂载文件
cat -> ${diskfs}/etc/fstab << EOF
# <file system> <dir> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
@ -229,6 +403,8 @@ title=$(cat<<EOF
\e[0m
EOF
)
# 生成 /etc/init.d/rcS 脚本
mkdir -pv ${diskfs}/etc/init.d
cat - > ${diskfs}/etc/init.d/rcS << EOF
#!/bin/sh
@ -238,18 +414,60 @@ echo -e "\n“${title}”\n"
cd /lib/modules && insmod hello_world.ko
# dns 测试 busybox 必须动态编译 动态编译 glibc 已经集成 dns 功能
ifconfig eth0 192.168.100.6 && ifconfig eth0 up
route add default gw 192.168.100.1
# qemu 网卡设置(调试方便)
# ifconfig eth0 192.168.100.6 && ifconfig eth0 up
# route add default gw 192.168.100.1
# vmware 网卡设置 ( 调试方便 )
ifconfig eth0 192.168.222.195 && ifconfig eth0 up
route add default gw 192.168.222.2
# exec 执行 /etc/init.d/rc.local 脚本
# 启动 sshd 服务,保证远程连接,调试跟踪非常方便
/usr/sbin/sshd
EOF
chmod +x ${diskfs}/etc/init.d/rcS
# 登陆 login shell ,非 non-login shell
if [ "${with_login}" = true ]; then
# 必须设置这个 /usr/libexe/upowerd 才能启动,否则,就会提示 "name lost, exiting"
echo "export DBUS_SYSTEM_BUS_ADDRESS=unix:path=/usr/local/var/run/dbus/system_bus_socket" >> ${diskfs}/etc/profile
echo "export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> ${diskfs}/etc/profile
echo "export LD_LIBRARY_PATH=/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:/usr/lib/x86_64-linux-gnu" >> ${diskfs}/etc/profile
else
# 必须设置这个 /usr/libexe/upowerd 才能启动,否则,就会提示 "name lost, exiting"
echo "export DBUS_SYSTEM_BUS_ADDRESS=unix:path=/usr/local/var/run/dbus/system_bus_socket" >> ${diskfs}/etc/profile
echo "export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" >> ${diskfs}/etc/bash.bashrc
echo "export LD_LIBRARY_PATH=/lib:/lib64:/usr/lib:/usr/lib64:/usr/local/lib:/usr/local/lib64:/usr/lib/x86_64-linux-gnu" >> ${diskfs}/etc/bash.bashrc
fi
echo "${GREEN}+++ build diskfs ok +++${NC}"
# 卸载映射
umount ${loop_dev}
losetup -d ${loop_dev}
#----------------------------------------------------------------
#
# 常用命令
#
#----------------------------------------------------------------
# 查看CPU信息cat /proc/cpuinfo
# 查看板卡信息cat /proc/pci
# 查看PCI信息lspci (相比cat /proc/pci更直观)
# 查看内存信息cat /proc/meminfo
# 查看USB设备cat /proc/bus/usb/devices
# 查看键盘和鼠标:cat /proc/bus/input/devices
# 查看系统硬盘信息和使用情况fdisk & disk - l & df
# 查看各设备的中断请求(IRQ):cat /proc/interrupts
# 查看系统体系结构uname -a
# dmidecode查看硬件信息包括bios、cpu、内存等信息
# dmesg | more 查看硬件信息
# modinfo命令可以单看指定的模块/驱动的信息
# 查看设备名称 cat /sys/class/input/mouse2/device/name
# linux为什么访问设备数据先要mount? https://www.zhihu.com/question/524667726
#---------------------------------------------------------------
#
# 查看磁盘内容
@ -257,4 +475,13 @@ losetup -d ${loop_dev}
#---------------------------------------------------------------
./ls_img.sh
#---------------------------------------------------------------
#
# 转换为 vmware 格式, 虚拟机的磁盘类型一定设置为 SATA ,否则启动失败
# SCSI 格式转换, 命令查询 : qemu-img convert -O vmdk -o ?
# 需要二次转换 vmkfstools -i 11.vmdk esxi-compatible.vmdk
#
#---------------------------------------------------------------
qemu-img convert disk.img -f raw -O vmdk disk_sata.vmdk
echo "Run the next script: 03_run_qemu.sh or 04_run_docker.sh"

View File

@ -91,6 +91,9 @@ else
sdb_img="-hdb extra.img"
fi
# 指定内存
memory="-m 4G"
# 主磁盘
disk="-drive format=raw,file=disk.img"
@ -101,8 +104,11 @@ logfile="-serial file:./qemu.log"
# 网络参数
network="-netdev tap,id=nd0,ifname=tap0,script=no,downscript=no -device e1000,netdev=nd0"
# 启动镜像 网络对应 run_nat.sh 里面的配置
qemu-system-x86_64 ${disk} ${sdb_img} ${network} ${logfile}
# 显卡参数 需要编译 xf86-video-vmware, see mk_xfce.sh
display="-vga qxl"
# 启动镜像 网络对应 run_nat.sh 里面的配置 ( -enable-kvm : vmware 里面 CPU 设置需要支持虚拟化 Intel VT-x/EPT 或 AMD-V/RVI )
# 命令 qemu-system-x86_64 -device help 可以查看支持哪些设备
qemu-system-x86_64 -device qxl ${display} ${memory} ${disk} ${sdb_img} ${network} ${logfile}
# stop nat
stop_nat

View File

@ -1,16 +1,20 @@
# smart-os 一个小巧的 linux 系统
本项目给大家演示了怎么样快速制作一个小巧功能齐全的 linux 操作系统, 项目地址 https://github.com/superconvert/smart-os
本项目给大家演示了怎么样快速制作一个小巧功能齐全的 linux 操作系统, 项目地址 https://github.com/superconvert/smart-os
# 功能与特点
1. 支持挂载多块硬盘
2. 支持网络功能
3. 支持 DNS 域名解析
4. 支持 GCC 编译器
5. 支持 qemu 启动
6. 支持 docker 启动
7. 最精简模式 64 M
8. 支持驱动相关演示
9. 支持 smart_rtmpd 流媒体服务器运行 https://github.com/superconvert/smart_rtmpd
1. 支持挂载多硬盘挂载
2. 支持网络功能DNS 解析
3. 支持 GCC 编译器cc++
4. 支持 qemu 方式启动
5. 支持 docker 方式启动
6. 系统最精简模式 64 M大小
7. 支持驱动制作相关演示
8. 支持防火墙 iptables
9. 支持远程服务 openssh-server
10. 支持桌面系统 xfce4 desktop
![avatar](xfce4.png)
11. 支持常用工具集 lshwlspcilsofstrace 等
12. 支持 smart_rtmpd 流媒体服务器运行 https://github.com/superconvert/smart_rtmpd
# 用途与场景
1. 操作系统原理教学
@ -23,7 +27,15 @@
1. 增加 arm 版本
2. 增加图形界面演示
3. 支持 ISO 制作
4. 防火墙
4. 时区
# 整体思路演进
1. 我们为什么选择 server 版本进行制作?
server 版本不包含窗口系统所依赖的大部分包;如果系统自带这些包,就会存在包的多版本的问题,编译问题,依赖问题,链接问题,运行时问题,会给我们的给工作带来很多干扰,况且解决这些问题都是无意义的,我们需要纯净版本的依赖包
2. 为什么窗口系统工作如此庞大?
我们所有利用 apt 安装的包(工具除外),理论上都需要我们进行源码编译,包括包的依赖及粘连,都需要解决,这是一个极其庞大的工作量,没办法,新系统上一无所有,所需的环境都需要我们交叉编译提供出来。工程 A 依赖包 b ,包 b 依赖包 c, 包 c 又依赖包 d我们所要做的就是把所有的包都需要编译出来
# 制作流程
本脚本 Ubuntu 18.04 上做的,别的系统应该改动不大,有需要的朋友可以自行修改。
@ -112,7 +124,10 @@
4. 我们怎么跟踪一个可执行程序的加载那些库,利用 LD_DEBUG=libs ./test 就可以了, 我们预加载库可以利用 LD_PRELOAD 强制预加载库
5. 我们编译 cairo 通常情况下会遇到很多问题,如果 cairo 编译出现问题,怎么办,有些错误信息网上很难搜到
一定看它编译时生成的 config.log 文件,错误信息很详细!可以根据提示信息去解决问题
一定看它编译时生成的 config.log 文件,错误信息很详细!可以根据提示信息去解决问题
6. 关于 busybox 的 init 系统变量
即使利用 grub 的内核参数传递环境变量也不行busybox 的 init 会自动生成默认的环境变量 PATH ,因此需要改动源码支持自定制路径。当然 shell 的登录模式,会读取 /etc/profile ,对于非登录模式,此模式失效,所以通过 /etc/profile 有局限性。
# libxcb 的编译,具体详情参见 mk_xorg.sh
1. 需要安装 apt install -y python-xcbgen 这个库,这个库会根据 xcbproto 提供的 xml 文件生成对应的 h 文件和 c 文件
@ -134,7 +149,16 @@
6. 编译有循环依赖的比如freetype && harfbuzz && cairo 具体解决方式,参见 mk_xfce.sh 脚本的处理
# 有关 xfce4 的编译,配置,安装与运行
这块知识牵涉的知识相对比较庞大,国内包括国外专门介绍 xfce4 的编译及使用文章相对较少,我也是摸着石头过河,尽量把这块知识演示清楚,我会专门开一个章节专门讲解这个,对于 xfce4 移植到 smart-os 内,我没有十分的把握,但我会尽力做到这一点,给国人揭示图形系统的奥秘
这块知识牵涉的知识相对比较庞大,国内包括国外专门介绍 xfce4 的编译及使用文章相对较少,我也是摸着石头过河,尽量把这块知识演示清楚,我会专门开一个章节专门讲解这个,对于 xfce4 移植到 smart-os 内,给国人揭示图形系统的奥秘,具体详情请参见 [xfce4.md](./xfce4.md)
# 桌面系统的总结
整个图形系统的整合工作量特别庞大,牵涉到系统的方方面面,国外相关此方面系统性的资料都比较少,国内几乎就更少了。目标是全部自己 DIY 所有的环境个人的开源项目让整个图形系统完整的运行起来smart-os 不是第一个,基本上也是前三名。目前我还不知道。整个整合过程非常漫长,遇到的问题非常非常多,不断的调试,编译,这些重复性的工作就不说了,工作量特别庞大,我几乎可以用呕心沥血来形容我的工作,绝对不为过。其次,遇到的知识点也比较多,很多都是现学现卖,需要迅速了解其工作机制,出问题的原因,然后解决问题。下面就整体的思路大体说一下,方便新学者,快速了解思路,对系统维护有个指引,对于解决系统性问题提供一个模型。
1. 硬件模块必须具备,图形系统基本要求 显示器 + 显卡 + 输入(键盘,鼠标),本项目基本上就是采用 vmware 和 qemu 软件,软件自带各类模拟硬件
2. 驱动目前内核基本上都支持,需要一一寻找相关资料,需要很多驱动,这些对内核进行配置,并开启大部分以 built-in 的方式,编译到内核,具体参考 <<01_build_src.sh>> 内核配置文件替换的部分
xorg 输入驱动, xorg 视频驱动xorg 视频加速 ( 可选 ), 常用的设备 /dev/input/xxx, /dev/dri/xxx 等
3. 服务层部分,我们用到了 dbus-1, udevddbus-1 如果配置不正确,会导致 upower 相关部分的组件不能正常工作xwindows 的整个运转也有问题udevd 不正常工作,会导致鼠标,键盘不能正常工作,导致进入界面后,这些设备都不能正常工作;此外 dbus 的用户需要创建,环境变量需要配置
4. xorg 层面对键盘数据schema, font 等基本数据都需要安装和产生,最关键的还是有 mine 数据库 desktop 的 application 都需要产生对应的数据, xinit 负责 x client 和 xserver 同时拉起,当然也可以手工一个 shell 里面启动 xorg 另外一个 shell 里面启动 xfce4-session这种模式对于调试比较方便我们调试单个组件的启动都是用这个方式比较方便
# 拓展知识

View File

@ -18,49 +18,91 @@ NC='\e[0m' # 没有颜色
# 处理器
core_num=`nproc`
# 是否开启 ssh
with_ssh=true
# 是否开启 ufw
with_ufw=true
# 是否开启 gcc
with_gcc=true
# 是否开启 xorg
with_xorg=false
# 是否带有工具
with_util=true
# 是否开启 xfce
with_xfce=false
# 开启编译后 xfce 本地测试
with_xfce_test=true
# 是否开启 xfce ( 需要开启 gcc )
with_xfce=true
# 是否挂载第二块硬盘
with_sdb=false
# 是否登陆模式
with_login=false
# 编译工程目录
build_dir=`pwd`"/build"
with_login=true
#----------------------------------------------
# 公共目录
#----------------------------------------------
build_dir=`pwd`"/build"
linux_install=${build_dir}"/linux_install"
glibc_install=${build_dir}"/glibc_install"
busybox_install=${build_dir}"/busybox_install"
lshw_install=${build_dir}"/lshw_install"
lsof_install=${build_dir}"/lsof_install"
strace_install=${build_dir}"/strace_install"
pciutils_install=${build_dir}"/pciutils_install"
openssl_install=${build_dir}"/openssl_install"
openssh_install=${build_dir}"/openssh_install"
libmnl_install=${build_dir}"/libmnl_install"
libnftnl_install=${build_dir}"/libnftnl_install"
iptables_install=${build_dir}"/iptables_install"
gcc_install=${build_dir}"/gcc_install"
binutils_install=${build_dir}"/binutils_install"
xorg_install=${build_dir}"/xorg_install"
xfce_install=${build_dir}"/xfce_install"
#----------------------------------------------
# 从完整路径获取文件名
#----------------------------------------------
file_name() {
filename=$(echo $1 | rev | awk -v FS='/' '{print $1}' | rev)
echo ${filename}
}
#----------------------------------------------
# 获取去掉扩展名的文件名
#----------------------------------------------
file_dirname() {
filename=$(file_name $1)
filedir=`echo $filename | sed "s/$2//g"`
echo $filedir
}
#----------------------------------------------
# 下载一个指定 URL 的源码包, 并存为指定的名字
#----------------------------------------------
download_src() {
SRC_NAME=$2$(file_name $1)
if [ ! -f ${SRC_NAME} ]; then
wget -c -t 0 $1 -O $SRC_NAME --no-check-certificate || (echo "download $1 failed" && exit)
fi
echo $SRC_NAME
}
#----------------------------------------------
# 解压一个下载的源码包到去掉扩展名的目录内
#----------------------------------------------
unzip_src() {
SRC_NAME=$2
SRC_DIR=${build_dir}"/"$(file_dirname ${SRC_NAME} $1)
if [ ! -d ${SRC_DIR} ]; then
tar xf source/${SRC_NAME} -C ${build_dir}
fi
echo $SRC_DIR
}
#----------------------------------------------
# 获取一个目录下所有的文件,包括子目录
#----------------------------------------------
ls_dir() {
for file in `ls $1`
do
@ -74,3 +116,23 @@ ls_dir() {
done
}
#---------------------------------------------
# 创建一个磁盘文件并分区
#---------------------------------------------
create_disk() {
# 输入参数磁盘文件和大小
disk=$1
size=$2
# 创建一个磁盘文件
dd if=/dev/zero of=${disk} bs=1M count=${size}
# 对磁盘进行分区一个主分区
fdisk ${disk} << EOF
n
p
w
EOF
}

View File

@ -27,9 +27,9 @@ EOF
cat<<EOF>Makefile
obj-m += hello_world.o
all:
make -C ../build/linux-4.14.9 M=`pwd` modules
make -C ../build/linux-5.8.6 M=`pwd` modules
clean:
make -C ../build/linux-4.14.9 M=`pwd` clean
make -C ../build/linux-5.8.6 M=`pwd` clean
EOF
echo $1

View File

@ -10,6 +10,7 @@ EOF
# 用户密码文件
cat<<EOF>${diskfs}/etc/passwd
root:x:0:0:root:/:/bin/sh
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
EOF
# 用户 shadow 文件
@ -30,12 +31,5 @@ export PS1 HOSTNAME
EOF
# 重新生成 inittab 文件
cat<<EOF>${diskfs}/etc/inittab
::sysinit:/bin/hostname -F /etc/hostname
::sysinit:/etc/init.d/rcS
tty0::respawn:-/bin/login
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
EOF
sed -i "1i\::sysinit:\/bin\/hostname -F \/etc\/hostname" ${diskfs}/etc/inittab
sed -i "1i\# 加载主机名称" ${diskfs}/etc/inittab

View File

@ -1,5 +1,8 @@
#!/bin/sh
# 导入公共环境
. ./common.sh
#----------------------------------------------
#
# 制作磁盘
@ -13,18 +16,7 @@ fi
echo "${CYAN}开始制作磁盘...${NC}"
# 创建磁盘 64M
dd if=/dev/zero of=extra.img bs=1M count=64
# 对磁盘进行分区一个主分区
fdisk extra.img << EOF
n
p
w
EOF
create_disk extra.img 64
echo "${GREEN}磁盘制作成功!!!${NC}"
echo ".........................................................."

View File

@ -3,6 +3,7 @@
# 导入公共环境
. ./common.sh
# 对指定的目录进行 strip
strip_dir() {
for file in `ls $1`
do
@ -32,7 +33,25 @@ strip_dir ${glibc_install}
# strip busybox
rm -rf ${busybox_install}/linuxrc
strip ${busybox_install}/bin/busybox
strip_dir ${busybox_install}/bin/busybox
# strip lshw
strip_dir ${lshw_install}
# strip pciutils_install
strip_dir ${pciutils_install}
# strip lsof
strip_dir ${lsof_install}
# strip strace
strip_dir ${strace_install}
# strip openssl
strip_dir ${openssl_install}
# strip openssh
strip_dir ${openssh_install}
# strip gcc
#rm -rf work/libgcc_install/usr/share
@ -42,3 +61,7 @@ strip_dir ${gcc_install}
#rm -rf work/binutils_install/usr/share
strip_dir ${binutils_install}
# strip xfce
if [ "${with_xfce}" = true ]; then
strip_dir ${xfce_install}
fi

1467
mk_xfce.sh

File diff suppressed because it is too large Load Diff

View File

@ -29,12 +29,7 @@ XSVR_SRC_URL=https://www.x.org/archive/individual/xserver/xorg-server-1.20.11.ta
#----------------------------
mkdir -pv source
cd source
XSVR_SRC_NAME=$(file_name ${XSVR_SRC_URL})
if [ ! -f ${XSVR_SRC_NAME} ]; then
wget -c -t 0 $XSVR_SRC_URL
fi
XSVR_SRC_NAME=$(download_src ${XSVR_SRC_URL})
cd ..
#---------------------------
@ -43,12 +38,7 @@ cd ..
#
#---------------------------
mkdir -pv ${build_dir}
XSVR_SRC_DIR=${build_dir}"/"$(file_dirname ${XSVR_SRC_NAME} .tar.bz2)
if [ ! -d ${XSVR_SRC_DIR} ]; then
echo "unzip ${XSVR_SRC_NAME} source code"
tar xf source/${XSVR_SRC_NAME} -C ${build_dir}
fi
XSVR_SRC_DIR=$(unzip_src ".tar.bz2" ${XSVR_SRC_NAME}); echo "unzip ${XSVR_SRC_NAME} source code"
#---------------------------------------------
#
@ -110,89 +100,37 @@ else
tar zxf xclient.tar.gz
fi
echo "${GREEN}build macros begin${NC}"
cd macros
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build macros success${NC}"
cd .. && sleep 1
#---------------------------
# 公共编译函数定义
#---------------------------
xorg_build() {
local name=$1
echo "${GREEN}build ${name} begin${NC}" && cd ${name}
if [ "${name}" = "libxcb" ]; then
# 解决 libxcb 编译问题
sed -i "8 i reload(sys)" src/c_client.py
sed -i "9 i sys.setdefaultencoding('utf8')" src/c_client.py
fi
./autogen.sh && ./configure ${CFGOPT}
make -j8 && make install DESTDIR=${xclient_dir} && echo "${GREEN}build ${name} success${NC}"
cd .. && sleep 1
}
echo "${GREEN}build xcbproto begin${NC}"
cd xcbproto
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build xcbproto success${NC}"
cd .. && sleep 1
echo "${GREEN}build xorgproto begin${NC}"
cd xorgproto
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build xorgproto success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxau begin${NC}"
cd libxau
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxau success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxcb begin${NC}"
cd libxcb
# 解决 libxcb 编译问题
sed -i "8 i reload(sys)" src/c_client.py
sed -i "9 i sys.setdefaultencoding('utf8')" src/c_client.py
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxcb success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxtrans begin${NC}"
cd libxtrans
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxtrans success${NC}"
cd .. && sleep 1
echo "${GREEN}build libx11 begin${NC}"
cd libx11
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libx11 success${NC}"
cd .. && sleep 1
echo "${GREEN}build libice begin${NC}"
cd libice
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libice success${NC}"
cd .. && sleep 1
echo "${GREEN}build libsm begin${NC}"
cd libsm
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libsm success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxt begin${NC}"
cd libxt
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxt success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxext begin${NC}"
cd libxext
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxext success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxmu begin${NC}"
cd libxmu
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxmu success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxpm begin${NC}"
cd libxpm
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxpm success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxaw begin${NC}"
cd libxaw
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxaw success${NC}"
cd .. && sleep 1
echo "${GREEN}build libxdmcp begin${NC}"
cd libxdmcp
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build libxdmcp success${NC}"
cd .. && sleep 1
echo "${GREEN}build xload begin${NC}"
# 编译 xclient application
cd xload
./autogen.sh && ./configure ${CFGOPT} && make -j8 && make install -j8 DESTDIR=${xclient_dir} && echo "${GREEN}build xload success${NC}"
cd .. && sleep 1
xorg_build macros
xorg_build xcbproto
xorg_build xorgproto
xorg_build libxau
xorg_build libxcb
xorg_build libxtrans
xorg_build libx11
xorg_build libice
xorg_build libsm
xorg_build libxt
xorg_build libxext
xorg_build libxmu
xorg_build libxpm
xorg_build libxaw
xorg_build libxdmcp
xorg_build xload
cd ..

338
samba.md Normal file
View File

@ -0,0 +1,338 @@
# samba 配置整体说明
samba 是基于 smb 协议实现的不同系统之间实现文件共享打印资源共享的一套框架。smb 协议用来解决局域网内的文件或打印机等资源共享的问题,由微软公司和英特尔公司共同制定。
目前主要的类 UNIX 系统平台都支持此协议,这样在大部分常用的系统中都满足文件共享及打印资源共享需求。
samba 分为服务器端和客户端,本文档基于 UOS Server 20 1070a 作为 Samba 服务器做基准win10, win11 作为客户端为基准,进行配置流程说明
# samba 服务器端
下面的章节主要是阐述服务器端一些准备工作,包括安装,环境配置,运行等基本工作
## 安装 samba
~~~shell
yum install -y samba
~~~
## 查询是否安装 samba
~~~shell
[root@localhost ~]# rpm -qa | grep samba
samba-common-tools-4.17.5-2.0.1.uelc20.03.x86_64
samba-ldb-ldap-modules-4.17.5-2.0.1.uelc20.03.x86_64
samba-client-libs-4.17.5-2.0.1.uelc20.03.x86_64
samba-4.17.5-2.0.1.uelc20.03.x86_64
samba-libs-4.17.5-2.0.1.uelc20.03.x86_64
samba-dcerpc-4.17.5-2.0.1.uelc20.03.x86_64
samba-common-libs-4.17.5-2.0.1.uelc20.03.x86_64
samba-common-4.17.5-2.0.1.uelc20.03.noarch
~~~
如果出现上述包,则表明 samba 已经安装成功
## 开通防火墙放行
~~~shell
firewall-cmd --zone=public --add-port=139/tcp --permanent
firewall-cmd --zone=public --add-port=445/tcp --permanent
firewall-cmd --reload 或 systemctl restart firewalld
~~~
## 开通 SELinux 放行或关闭 SELinux
~~~shell
setsebool -P samba_enable_home_dirs=1
chcon -t samba_share_t /home/centos/share ---> 放行的目录
~~~
经过验证系统默认不阻挡 samba 服务器对外提供服务,这一步可以省略!!!
## 运行 samba 服务
~~~shell
systemctl restart smb.service
~~~
理想情况下都是启动成功,如果出现失败,会出现很多提示信息,根据信息进行排查,下面就一些错误进行简单的说明
1. 配置文件格式错误
samba 配置文件错误会导致 samba 启动失败比如yes 多了空格, set_variable_helper(yes ): value is not boolean
2. 查看启动失败原因
tail -f /var/log/samba/log.smbd
## 查看运行状态
~~~shell
[root@localhost ~]# systemctl status smb.service
● smb.service - Samba SMB Daemon
Loaded: loaded (/usr/lib/systemd/system/smb.service; disabled; vendor preset: disabled)
Active: active (running) since Tue 2025-02-25 04:00:58 CST; 5min ago
Docs: man:smbd(8)
man:samba(7)
man:smb.conf(5)
Main PID: 13499 (smbd)
Status: "smbd: ready to serve connections..."
Tasks: 3
Memory: 4.1M
CGroup: /system.slice/smb.service
├─13499 /usr/sbin/smbd --foreground --no-process-group
├─13501 /usr/sbin/smbd --foreground --no-process-group
└─13502 /usr/sbin/smbd --foreground --no-process-group
2月 25 04:00:58 localhost.localdomain systemd[1]: Starting Samba SMB Daemon...
2月 25 04:00:58 localhost.localdomain smbd[13499]: [2025/02/25 04:00:58.114320, 0] ../../source3/smbd/server.c:1741(main)
2月 25 04:00:58 localhost.localdomain smbd[13499]: smbd version 4.17.5 started.
2月 25 04:00:58 localhost.localdomain smbd[13499]: Copyright Andrew Tridgell and the Samba Team 1992-2022
2月 25 04:00:58 localhost.localdomain smbd[13499]: [2025/02/25 04:00:58.115092, 0] ../../lib/param/loadparm.c:749(lpcfg_map_parameter)
2月 25 04:00:58 localhost.localdomain smbd[13499]: Unknown parameter encountered: "browse"
2月 25 04:00:58 localhost.localdomain smbd[13499]: [2025/02/25 04:00:58.115138, 0] ../../lib/param/loadparm.c:1936(lpcfg_do_service_parameter)
2月 25 04:00:58 localhost.localdomain smbd[13499]: Ignoring unknown parameter "browse"
2月 25 04:00:58 localhost.localdomain systemd[1]: Started Samba SMB Daemon.
~~~
我们发现状态 active (running) 表明 samba 服务器启动成功。
## 查看运行端口
~~~shell
[root@localhost ~]# netstat -anp | grep smbd
tcp 0 0 192.168.112.132:139 0.0.0.0:* LISTEN 13499/smbd
tcp 0 0 192.168.112.132:445 0.0.0.0:* LISTEN 13499/smbd
unix 2 [ ] DGRAM 336690 13499/smbd /var/lib/samba/private/msg.sock/13499
unix 2 [ ] DGRAM 335554 13501/smbd /var/lib/samba/private/msg.sock/13501
unix 2 [ ] DGRAM 334795 13502/smbd /var/lib/samba/private/msg.sock/13502
unix 3 [ ] STREAM CONNECTED 335562 13499/smbd
unix 2 [ ] STREAM CONNECTED 336695 13499/smbd
unix 2 [ ] DGRAM 336673 13499/smbd
~~~
我们看到端口 139 和 445 已经正确绑定
## 配置文件说明
配置文件就是 /etc/samba/smb.conf 这里面的内容太多,大部分采用默认配置即可,没必要一一进行解释和使用。
# windows 客户端配置
## windows 配置 SMB 功能
windows 需要开启 SMB 1.0/CIFS 共享文件支持 分别从系统设置里面进行配置,配置完成,需要重启机器
win11 ---> 设置 ---> 应用 ---> 可选功能 ---> 更多 windows 功能 ---> SMB 1.0/CIFS 共享文件支持
win10 ---> 设置 ---> 应用 ---> 程序和功能 ---> 启用或关闭 windows 功能 ---> SMB 1.0/CIFS 共享文件支持
# 基本使用场景说明
下面就针对组,用户,配置文件,使用场景进行分别说明,由于是对账号和组的操作,所以必须在 root 账号下进行操作。
## 组管理
这里可以根据咱们的部门进行分组比如td(技术部), fd(财务部), md(市场部),这样对应部门的用户可以加入到相应的组内
1. 添加组 技术部
~~~shell
groupadd td
~~~
2. 删除组 技术部
~~~shell
groupdel td
~~~
3. 查看组成员
~~~shell
cat /etc/group | grep 组名
~~~
这是属于 linux 的一些基本命令,不一一介绍了
4. 要查看 samba 用户所属的用户组
~~~shell
pdbedit -Lv -u <samba用户名>
~~~
## 用户 管理
添加用户需要两步,第一步是添加系统用户,其次是添加 samba 用户
1. 添加用户
1.1 添加系统用户( 不能登录系统 )
~~~shell
useradd -s /sbin/nologin dev001
~~~
1.2 添加 samba 用户,并配置密码
~~~shell
smbpasswd -a dev001
~~~
2. 删除用户
2.1 删除 samba 用户
~~~shell
smbpasswd -x dev001
~~~
2.2 删除系统用
~~~shell
userdel dev001
~~~
3. 把用户添加到组
把用户 dev001 添加到组 td 中
~~~shell
usermod -a -G td dev001
~~~
4. 把用户从组中删除
把用户 dev001 从组 td 中删除
~~~shell
gpasswd -d dev001 td
~~~
## 配置文件说明
1. 配置文件路径
/etc/samba/smb.conf
2. 配置项说明
通常情况下smb.conf 配置文件是不需要修改的,如果我们想共享一个目录,则需要追加类似下面格式的文字到 smb.conf保存后重新启动 samba 服务
~~~shell
[company] # 共享名
comment = company share # 注释说明
path = /home/company # 共享文件路径
guest ok = no # 不允许匿名访问
writeable = yes # 允许用户写入数据
browseable = no # 当设置为 yes 时,表示该共享目录是可浏览的,其他计算机上的用户可以在网络浏览器中看到该共享目录,并能够浏览其中的文件和文件夹
# 当设置为no时表示该共享目录是不可浏览的其他计算机上的用户无法在网络浏览器中看到该共享目录从而增加共享资源的隐私保护 ---> 虽然看不到,但输入路径还是能进入的
printable = no #
valid users=admin,xsuser # 指定用户访问
write list=xzuser # 指定用户有写入权限
read list=user2
create mask = 755 # 新建文件掩码
directory mask = 755 # 新建目录掩码
host allow = 192.168.0. EXCEPT 192.168.0.99 # 只允许192.168.0.0/24但不包括192.168.0.99的客户端访问Samba服务器上的smbtest目录。
192.168.0.99 192.168.0.100 # 中间是空格
hosts deny :拒绝访问
~~~
# 配置示例
1. 场景描述
领导王总wangzong)
正式员工:张三(zhang3), 李四(li4),于老大(yu1), 于老二(yu2)
实习生:楚乔乔(chuxx),小马(xiaoma)
整个共享区域分为两部分,日常区,读写区,其中王总有整个盘的读写权限,子目录如下:
1.1 日常区
| 子目录 | 读写权限 | 查询权限 |
| --- | --- | --- |
| 重大事项 | wangzong | |
| 财务报表 | li4 | yu1, yu2 |
| 战略规划 | li4, yu1 | 正式员工 |
| 公司建议 | 正式员工 | |
| 共享资料 | 正式员工 | 实习生 |
1.2 读写区
| 子目录 | 读写权限 |
| --- | --- |
| 周报总结 | yu2 |
| 工作记录 | 正式员工 |
| 休闲娱乐 | 正式员工,实习生 |
2. 创建共享目录
~~~shell
[root@samba-server ~]# useradd samba
[root@samba-server ~]# mkdir -p /data/samba/daily
[root@samba-server ~]# mkdir -p /data/samba/read-write
[root@samba-server ~]# chown -R samba.samba /data/samba
~~~
共享根目录 /data/samba里面有两个目录 daily 和 read-write并把此目录所有者指定为 samba
3. 添加用户账号
~~~shell
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin wangzong
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin zhang3
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin li4
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin yu1
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin yu2
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin chuxx
[root@samba-server ~]# useradd -d /data/samba -s /sbin/nologin xiaoma
~~~
4. 创建对应的 samba 用户
~~~shell
[root@samba-server ~]# smbpasswd -a wangzong
new password:
retype new password:
.......
~~~
依次把用户添加进来,这里只举例了 wangzong 这个账号
5. 设置共享目录的权限
~~~shell
# 日常区配置
[root@samba-server samba]# cd daily
[root@samba-server daily]# mkdir 重大事项
[root@samba-server daily]# chown -R wangzong.wangzong /data/samba/daily/重大事项
[root@samba-server daily]# chmod -R 700 /data/samba/daily/重大事项
[root@samba-server daily]# mkdir 财务报表
[root@samba-server daily]# chown -R li4.li4 /data/samba/daily/财务报表
[root@samba-server daily]# chmod -R 700 /data/samba/daily/财务报表
[root@samba-server daily]# setfacl -R -m u:yu1:rx /data/samba/daily/财务报表
[root@samba-server daily]# setfacl -R -m u:yu2:rx /data/samba/daily/财务报表
[root@samba-server daily]# mkdir 战略规划
[root@samba-server daily]# chown -R li4.li4 /data/samba/daily/战略规划
[root@samba-server daily]# chmod -R 700 /data/samba/daily/战略规划
[root@samba-server daily]# setfacl -R -m u:yu1:rwx /data/samba/daily/战略规划
[root@samba-server daily]# setfacl -R -m g:regular:rx /data/samba/daily/战略规划
// 把正式员工添加到正式员工 (regular) 的组内
[root@samba-server daily]# gpasswd -a zhang3 regular
[root@samba-server daily]# gpasswd -a li4 regular
[root@samba-server daily]# gpasswd -a yu1 regular
[root@samba-server daily]# gpasswd -a yu2 regular
[root@samba-server daily]# mkdir 公司建议
[root@samba-server daily]# chown -R zhang3.zhang3 /data/samba/daily/公司制度
[root@samba-server daily]# chmod -R 700 /data/samba/daily/公司制度
[root@samba-server daily]# setfacl -R -m g:regular:rwx /data/samba/daily/公司制度
[root@samba-server daily]# mkdir 共享资料
[root@samba-server daily]# chown -R zhang3.zhang3 /data/samba/daily/共享资料
[root@samba-server daily]# chmod -R 700 /data/samba/daily/共享资料
[root@samba-server daily]# setfacl -R -m g:regular:rwx /data/samba/daily/共享资料
[root@samba-server daily]# setfacl -R -m g:intern:rx /data/samba/daily/共享资料
// 把实习生添加到实习生 (intern) 的组内
[root@samba-server daily]# gpasswd -a chuxx intern
[root@samba-server daily]# gpasswd -a xiaoma intern
# 读写区
[root@samba-server daily]# cd ../read-write/
[root@samba-server read-write]# mkdir /data/samba/read-write/周报总结
[root@samba-server read-write]# chown -R yu2.yu2 /data/samba/read-write/周报总结
[root@samba-server read-write]# chmod -R 700 /data/samba/read-write/周报总结
[root@samba-server read-write]# mkdir /data/samba/read-write/工作记录
[root@samba-server read-write]# chown -R zhang3.zhang3 /data/samba/read-write/工作记录
[root@samba-server read-write]# chmod -R 700 /data/samba/read-write/工作记录
[root@samba-server read-write]# setfacl -R -m g:regular:rwx /data/samba/read-write/作记录
[root@samba-server read-write]# mkdir /data/samba/read-write/休闲娱乐
[root@samba-server read-write]# chown -R zhang3.zhang3 /data/samba/read-write/休闲娱乐
[root@samba-server read-write]# chmod -R 700 /data/samba/read-write/休闲娱乐
[root@samba-server read-write]# setfacl -R -m g:regular:rwx /data/samba/read-write/休闲娱乐
[root@samba-server read-write]# setfacl -R -m g:intern:rwx /data/samba/read-write/休闲娱乐
~~~
王总 (wangzong) 对整个共享具有读写权限, 还要赋权给王总
~~~shell
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/daily/重大事项
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/daily/财务报表
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/daily/战略规划
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/daily/公司建议
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/daily/共享资料
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/read-write/周报总结
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/read-write/工作记录
[root@samba-server ~]# setfacl -R -m u:wangzong:rwx /data/samba/read-write/休闲娱乐
~~~
6. 修订 samba 服务器配置文件
编辑 /etc/samba/smb.conf追加
~~~shell
[share]
comment = "公司共享文件系统s"
path= /data/samba
public = no
valid users = wangzong,zhang3,li4,yu1,yu2,chuxx,xiaoma,@samba
printable = no
write list = wangzong,zhang3,li4,yu1,yu2,chuxx,xiaoma
7. 重启 samba 服务器
~~~shell
[root@samba-server ~]# systemctl restart smb.service
~~~

477
xfce4.md Normal file
View File

@ -0,0 +1,477 @@
# 单独运行 xfce4 组件 不编译 smart-os, 单独编译 xfce4
1. 利用 wmare 安装 Ubuntu 18.04 Server 版本,安装完毕,配置 apt 源ssh 等操作,就不要再做过多的操作了,尽量保持系统纯净
2. 修订 common.sh 文件里面的 with_xfce_test=true
3. ./mk_xfce.sh 进行 xfce4 的编译,编译完毕会自动生成 startxfce.sh
4. 重启系统,重启完毕。在 wmware 虚拟机里面执行 startxfce.sh 就可以成功拉起桌面了
运行效果图如下
![avatar](xfce4.png)
# xfce4 组件介绍
* [ Gtk+ ] 这些组件 gtk 最庞大
libffi
libmount
glib
pixman
freetype
harfbuzz
fontconfig
cairo
fribidi
pango
gdkpixbuf
libeproxy
graphene
wayland-protocols
gettext( libintl )
gtk+
* [ xfce ] 这些组件编译顺序也有要求
libwnck
xfce4-dev-tools
xlibxfce4util
xfconf
libxfce4ui
garcon
exo
xfce4-panel
thunar
xfce4-settings
xfce4-session
xfwm4
xfdesktop
thunar-volman
tumbler
xfce4-power-manager
xfce4-appfinder
# Cairo
cairo is a vector graphics library with cross-device output support
cairo能够做各种复杂的点线图案绘制、填充、文字渲染、图像变换、剪切、层混合等等操作。但是他没有涉及到用户交互如鼠标、touch、事件处理交互窗口这些统统没有他只有专一的绘图。他有surface可以理解为画布这个surface可以是基于内存image surface必选的surface也可以基于某种backend和操作系统或驱动接口对接使用过程是创建一个surface然后在surface里做各种绘图最后使用Painting类的functions时图像就显示在了surface上。当然surface也是一块image可以把image通过png源码有对接libpng库图像压缩输出png文件
# harfbuzz
HarfBuzz 是一个文本整形引擎。它主要支持OpenType但也 支持Apple Advanced Typography。HarfBuzz 用于 Android、Chrome、ChromeOS、Firefox、GNOME、GTK+、KDE、LibreOffice、OpenJDK、PlayStation、Qt、XeTeX 等地方。
# xfce 运行黑屏怎么办
比如黑屏,我们由屏幕想到可能是 xfdesktop 这个应用负责渲屏,黑屏可能是 xfdesktop 未能正确运行,这个就需要我们手工调试跟踪了,通常情况下我们会这么做:
```shell
# 设置屏幕,这个是 xfce 默认的值 10
export DISPLAY=:10
# 执行这个,正常执行理论上就不会黑屏,不能执行,可能是依赖库路径不对,版本不对,配置不对,逐步根据提示解决问题
xfdesktop
```
# xrdp 远程访问 linux 桌面流程分析( 重要
1. xrdp 服务依赖 xrdp-sesman 服务
我们可以通过 grep 全局查找 xrdp-sesman发现下面这句
```shell
./lib/systemd/system/xrdp.service:4:Requires=xrdp-sesman.service
```
因此 xrdp 启动时,肯定 xrdp-sesman 也相应启动,具体机制待研究(TODO)
2. 配置文件 /etc/xrdp/sesman.ini
```shell
[Globals]
ListenAddress=127.0.0.1
ListenPort=3350
```
3. 确认 xrdp 和 xrdp-sesman 服务
```shell
root@freeabc:/# netstat -anpt | grep xrdp
tcp6 0 0 :::3389 :::* LISTEN 6288/xrdp
tcp6 0 0 ::1:3350 :::* LISTEN 6259/xrdp-sesman
```
其中 xrdp 是 3389 对外提供服务, xrdp-sesman 是 3350 对 xrdp 提供服务xrdp 把请求转给 xrdp-sesman (经过 tcpdump 抓包确认是)
```shell
root@freeabc:/# tcpdump -s 0 -i lo port 3350 -v -n
tcpdump: listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
01:37:24.538435 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 40) ::1.52600 > ::1.3350: Flags [S], cksum 0x0030 (incorrect -> 0x3f1d), seq 213438096, win 65476, options [mss 65476,sackOK,TS val 4262615841 ecr 0,nop,wscale 7], length 0
01:37:24.538457 IP6 (flowlabel 0xe10b3, hlim 64, next-header TCP (6) payload length: 40) ::1.3350 > ::1.52600: Flags [S.], cksum 0x0030 (incorrect -> 0xbea4), seq 3363004107, ack 213438097, win 65464, options [mss 65476,sackOK,TS val 4262615841 ecr 4262615841,nop,wscale 7], length 0
01:37:24.538472 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 32) ::1.52600 > ::1.3350: Flags [.], cksum 0x0028 (incorrect -> 0xe53a), ack 1, win 512, options [nop,nop,TS val 4262615841 ecr 4262615841], length 0
01:37:25.149700 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 109) ::1.52600 > ::1.3350: Flags [P.], cksum 0x0075 (incorrect -> 0x6a7f), seq 1:78, ack 1, win 512, options [nop,nop,TS val 4262616452 ecr 4262615841], length 77
01:37:25.149734 IP6 (flowlabel 0xe10b3, hlim 64, next-header TCP (6) payload length: 32) ::1.3350 > ::1.52600: Flags [.], cksum 0x0028 (incorrect -> 0xe028), ack 78, win 511, options [nop,nop,TS val 4262616452 ecr 4262616452], length 0
01:37:25.216918 IP6 (flowlabel 0xe10b3, hlim 64, next-header TCP (6) payload length: 62) ::1.3350 > ::1.52600: Flags [P.], cksum 0x0046 (incorrect -> 0xd13d), seq 1:31, ack 78, win 512, options [nop,nop,TS val 4262616519 ecr 4262616452], length 30
01:37:25.216969 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 32) ::1.52600 > ::1.3350: Flags [.], cksum 0x0028 (incorrect -> 0xdf83), ack 31, win 512, options [nop,nop,TS val 4262616519 ecr 4262616519], length 0
01:37:25.254713 IP6 (flowlabel 0xe10b3, hlim 64, next-header TCP (6) payload length: 32) ::1.3350 > ::1.52600: Flags [F.], cksum 0x0028 (incorrect -> 0xdf5c), seq 31, ack 78, win 512, options [nop,nop,TS val 4262616557 ecr 4262616519], length 0
01:37:25.297973 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 32) ::1.52600 > ::1.3350: Flags [.], cksum 0x0028 (incorrect -> 0xdf0b), ack 32, win 512, options [nop,nop,TS val 4262616600 ecr 4262616557], length 0
01:37:25.886713 IP6 (flowlabel 0xc281a, hlim 64, next-header TCP (6) payload length: 32) ::1.52600 > ::1.3350: Flags [F.], cksum 0x0028 (incorrect -> 0xdcbd), seq 78, ack 32, win 512, options [nop,nop,TS val 4262617189 ecr 4262616557], length 0
01:37:25.886737 IP6 (flowlabel 0xc429c, hlim 64, next-header TCP (6) payload length: 32) ::1.3350 > ::1.52600: Flags [.], cksum 0x0028 (incorrect -> 0xda45), ack 79, win 512, options [nop,nop,TS val 4262617189 ecr 4262617189], length 0
01:37:41.603074 IP6 (flowlabel 0x461f5, hlim 64, next-header TCP (6) payload length: 32) ::1.46136 > ::1.3350: Flags [F.], cksum 0x0028 (incorrect -> 0x23fc), seq 3577026672, ack 1112127163, win 512, options [nop,nop,TS val 4262632906 ecr 4262596309], length 0
01:37:41.603101 IP6 (flowlabel 0xeaed7, hlim 64, next-header TCP (6) payload length: 32) ::1.3350 > ::1.46136: Flags [.], cksum 0x0028 (incorrect -> 0x9506), ack 1, win 512, options [nop,nop,TS val 4262632906 ecr 4262632906], length 0
```
我们也可以利用 journalctl -xf 查看日志
```shell
Aug 18 01:45:02 freeabc xrdp[10507]: (10507)(139797313210176)[INFO ] Socket 12: AF_INET6 connection received from ::ffff:192.168.222.1 port 56030
Aug 18 01:45:02 freeabc xrdp[10507]: (10507)(139797313210176)[DEBUG] Closed socket 12 (AF_INET6 ::ffff:192.168.222.178 port 3389)
Aug 18 01:45:02 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Closed socket 11 (AF_INET6 :: port 3389)
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] Using default X.509 certificate: /etc/xrdp/cert.pem
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] Using default X.509 key file: /etc/xrdp/key.pem
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] TLSv1.2 enabled
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] TLSv1.1 enabled
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] TLSv1 enabled
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Security layer: requested 11, selected 1
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] connected client computer name: DESKTOP-9PAUEP4
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] TLS connection established from ::ffff:192.168.222.1 port 56030: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_000029bf_wm_login_mode_event_00000001
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] Cannot find keymap file /etc/xrdp/km-00000804.ini
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] Cannot find keymap file /etc/xrdp/km-00000804.ini
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] Loading keymap file /etc/xrdp/km-00000409.ini
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[WARN ] local keymap file for 0x00000804 found and doesn't match built in keymap, using local keymap file
Aug 18 01:45:03 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_wm_log_msg: connecting to sesman ip 127.0.0.1 port 3350
Aug 18 01:45:03 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[INFO ] A connection received from ::1 port 36482
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] xrdp_wm_log_msg: sesman connect ok
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_wm_log_msg: sending login info to session manager, please wait...
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] return value from xrdp_mm_connect 0
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[INFO ] ++ created session (access granted): username root, ip ::ffff:192.168.222.1:56030 - socket: 12
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[INFO ] starting Xorg session...
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[DEBUG] Closed socket 9 (AF_INET6 :: port 5911)
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[DEBUG] Closed socket 9 (AF_INET6 :: port 6011)
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[DEBUG] Closed socket 9 (AF_INET6 :: port 6211)
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[INFO ] calling auth_start_session from pid 10688
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[DEBUG] Closed socket 8 (AF_INET6 ::1 port 3350)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] xrdp_wm_log_msg: login successful for display 11
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: pam_unix(xrdp-sesman:session): session opened for user root by (uid=0)
Aug 18 01:45:04 freeabc systemd-logind[1076]: New session c15 of user root.
-- Subject: A new session c15 has been created for user root
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
-- Documentation: https://www.freedesktop.org/wiki/Software/systemd/multiseat
--
-- A new session with the ID c15 has been created for the user root.
--
-- The leading process of the session is 10688.
Aug 18 01:45:04 freeabc systemd[1]: Started Session c15 of user root.
-- Subject: Unit session-c15.scope has finished start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit session-c15.scope has finished starting up.
--
-- The start-up result is RESULT.
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] Closed socket 7 (AF_INET6 ::1 port 3350)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_wm_log_msg: started connecting
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] Closed socket 8 (AF_INET6 ::1 port 3350)
Aug 18 01:45:04 freeabc xrdp-sesman[10690]: (10690)(140145709626688)[INFO ] /usr/lib/xorg/Xorg :11 -auth .Xauthority -config xrdp/xorg.conf -noreset -nolisten tcp -logfile .xorgxrdp.%s.log
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[CORE ] waiting for window manager (pid 10689) to exit
Aug 18 01:45:04 freeabc systemd[1487]: Started GnuPG cryptographic agent and passphrase cache.
-- Subject: Unit UNIT has finished start-up
-- Defined-By: systemd
-- Support: http://www.ubuntu.com/support
--
-- Unit UNIT has finished starting up.
--
-- The start-up result is RESULT.
Aug 18 01:45:04 freeabc gpg-agent[10760]: gpg-agent (GnuPG) 2.2.4 starting in supervised mode.
Aug 18 01:45:04 freeabc gpg-agent[10760]: using fd 3 for ssh socket (/run/user/0/gnupg/S.gpg-agent.ssh)
Aug 18 01:45:04 freeabc gpg-agent[10760]: using fd 4 for extra socket (/run/user/0/gnupg/S.gpg-agent.extra)
Aug 18 01:45:04 freeabc gpg-agent[10760]: using fd 5 for std socket (/run/user/0/gnupg/S.gpg-agent)
Aug 18 01:45:04 freeabc gpg-agent[10760]: using fd 6 for browser socket (/run/user/0/gnupg/S.gpg-agent.browser)
Aug 18 01:45:04 freeabc gpg-agent[10760]: listening on: std=5 extra=4 browser=6 ssh=3
Aug 18 01:45:04 freeabc kernel: xfce4-session[10742]: segfault at 2c ip 0000556e4a4fe8c6 sp 00007ffedc54cd30 error 4 in xfce4-session[556e4a4d2000+45000]
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] lib_mod_log_peer: xrdp_pid=10687 connected to X11rdp_pid=10690 X11rdp_uid=0 X11rdp_gid=0 client_ip=::ffff:192.168.222.1 client_port=56030
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_wm_log_msg: connected ok
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_mm_connect_chansrv: chansrv connect successful
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Closed socket 20 (AF_INET6 ::1 port 36482)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] The following channel is allowed: rdpdr (0)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] The following channel is allowed: rdpsnd (1)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] The following channel is allowed: cliprdr (2)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[INFO ] The following channel is allowed: drdynvc (3)
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] The allow channel list now initialized for this session
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[CORE ] window manager (pid 10689) did exit, cleaning up session
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[INFO ] calling auth_stop_session and auth_end from pid 10688
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: pam_unix(xrdp-sesman:session): session closed for user root
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] cleanup_sockets:
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Closed socket 22 (AF_UNIX)
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] cleanup_sockets: deleting /var/run/xrdp/sockdir/xrdp_chansrv_audio_out_socket_11
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Closed socket 12 (AF_INET6 ::ffff:192.168.222.178 port 3389)
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] cleanup_sockets: deleting /var/run/xrdp/sockdir/xrdp_chansrv_audio_in_socket_11
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] xrdp_mm_module_cleanup
Aug 18 01:45:04 freeabc xrdp[10687]: (10687)(139797313210176)[DEBUG] Closed socket 21 (AF_UNIX)
Aug 18 01:45:04 freeabc xrdp-sesman[10688]: (10688)(140145709626688)[DEBUG] cleanup_sockets: deleting /var/run/xrdp/sockdir/xrdpapi_11
Aug 18 01:45:04 freeabc xrdp-sesman[10471]: (10471)(140145709626688)[INFO ] ++ terminated session: username root, display :11.0, session_pid 10688, ip ::ffff:192.168.222.1:56030 - socket: 12
Aug 18 01:45:14 freeabc systemd-logind[1076]: Removed session c15.
-- Subject: Session c15 has been terminated
```
这个日志可以看到更清楚的流程,具体日志见上
我们看到这个没启动起来是 xfce4-session[10742]: segfault at 2c ip 0000556e4a4fe8c6 sp 00007ffedc54cd30 error 4 in xfce4-session[556e4a4d2000+45000] 有段错误
这个错误,我们可以单独运行 xfce4-session 查看原因
```shell
xfwm4-Message: 02:00:03.303: Another Window Manager (Xfwm4) is already running on screen :10.0
xfwm4-Message: 02:00:03.303: To replace the current window manager, try "--replace"
(xfwm4:11384): xfwm4-WARNING **: 02:00:03.303: Could not find a screen to manage, exiting
```
我们看到是另外一个 Xfwn4 已经启动在 screen :10.0 了,可以运行 xfwm4 --replace 替换一下
对用户的授权,我们通过日志可以观察到是通过文件 ~/.Xauthority
5. xrdp-sesman 会根据 sesman.ini 调用 /etc/xrdp/startwm.sh这个脚本最终会调用 /etc/X11/Xsession 这个脚本, Xsession 这个脚本大有文章
```shell
SYSSESSIONDIR=/etc/X11/Xsession.d
USERXSESSION=$HOME/.xsession ---> 看到没有这就是我们经常看到的很多文章推荐的 echo "xfce4-session" > ~/.xsession 的原因,设置 Xsession 的环境变量
...
SESSIONFILES=$(run-parts --list $SYSSESSIONDIR) ---> 最终会执行 /etc/X11/Xsession.d 下的脚本,我们所有的窗口会话实现,应该放到这个里面
if [ -n "$SESSIONFILES" ]; then
set +e
for SESSIONFILE in $SESSIONFILES; do
echo $SESSIONFILES >> /root/my.log
. $SESSIONFILE
done
set -e
fi
```
/etc/X11/Xsession.d/20dbus_xdg-runtime
/etc/X11/Xsession.d/20x11-common_process-args
/etc/X11/Xsession.d/30x11-common_xresources
/etc/X11/Xsession.d/35x11-common_xhost-local
/etc/X11/Xsession.d/40x11-common_xsessionrc
/etc/X11/Xsession.d/50x11-common_determine-startup
/etc/X11/Xsession.d/60x11-common_localhost
/etc/X11/Xsession.d/60x11-common_xdg_path
/etc/X11/Xsession.d/75dbus_dbus-launch
/etc/X11/Xsession.d/90gpg-agent
/etc/X11/Xsession.d/90qt-a11y
/etc/X11/Xsession.d/90x11-common_ssh-agent
/etc/X11/Xsession.d/95dbus_update-activation-env
/etc/X11/Xsession.d/99x11-common_start
参数 STARTUP 赋值
我们看到执行 /etc/X11/Xsession.d/50x11-common_determine-startup 时,会 STARTUP="$shell $STARTUPFILE" 其实就是 /bin/bash /root/.xsession , root就是 ~ 我们用 root 登录的。
参数 STARTUP 运行
我们跟踪执行 /etc/X11/Xsession.d/99x11-common_start/99x11-common_start 时exec $STARTUP 这个其实就是执行 xfce4-session 了,至此 xfce4-session 启动完成
xfce4-session 会读取 下面的文件,并执行里面的命令
https://manpages.ubuntu.com/manpages/xenial/man1/xfce4-session.1.html
xfce4-session reads its configuration from Xfconf. xfce4-session stores its session data into $XDG_CACHE_HOME/sessions/.
具体配置文件就是 /usr/local/etc/xdg/xfce4/xfconf/xfce-perchannel-xml/xfce4-session.xml
```xml
<?xml version="1.0" encoding="UTF-8"?>
<channel name="xfce4-session" version="1.0">
<property name="general" type="empty">
<property name="FailsafeSessionName" type="string" value="Failsafe"/>
<property name="LockCommand" type="string" value=""/>
</property>
<property name="sessions" type="empty">
<property name="Failsafe" type="empty">
<property name="IsFailsafe" type="bool" value="true"/>
<property name="Count" type="int" value="5"/>
<property name="Client0_Command" type="array">
<value type="string" value="xfwm4"/>
</property>
<property name="Client0_Priority" type="int" value="15"/>
<property name="Client0_PerScreen" type="bool" value="false"/>
<property name="Client1_Command" type="array">
<value type="string" value="xfsettingsd"/>
</property>
<property name="Client1_Priority" type="int" value="20"/>
<property name="Client1_PerScreen" type="bool" value="false"/>
<property name="Client2_Command" type="array">
<value type="string" value="xfce4-panel"/>
</property>
<property name="Client2_Priority" type="int" value="25"/>
<property name="Client2_PerScreen" type="bool" value="false"/>
<property name="Client3_Command" type="array">
<value type="string" value="Thunar"/>
<value type="string" value="--daemon"/>
</property>
<property name="Client3_Priority" type="int" value="30"/>
<property name="Client3_PerScreen" type="bool" value="false"/>
<property name="Client4_Command" type="array">
<value type="string" value="xfdesktop"/>
</property>
<property name="Client4_Priority" type="int" value="35"/>
<property name="Client4_PerScreen" type="bool" value="false"/>
</property>
</property>
</channel>
```
我们看到一个会话启动五个最基本的服务 xfwm4, xfsettingsd, xfce4-panel, Thunar, xfdesktop如果启动失败请依次排查这几个服务是否正常
如果只出状态栏和 Dock ,桌面出现黑屏,基本上是 xfdesktop 启动失败,可能依赖的库不满足,缺少什么库,这个需要具体问题具体分析了。
进程关系如下图
```shell
systemd--
|-xrdp---xrdp
|-xrdp-sesman---xrdp-sesman---Xorg---9*[{Xorg}]
|-bash---ssh-agent
| |-xfce4-session---Thunar---2*[{Thunar}]
| |-xfce4-panel---panel-14-action---2*[{panel-14-action}]
| | |-panel-6-systray---2*[{panel-6-systray}]
| | |-panel-9-power-m---2*[{panel-9-power-m}]
| | |-2*[{xfce4-panel}]
| |-xfce4-power-man---2*[{xfce4-power-man}]
| |-xfdesktop---2*[{xfdesktop}]
| |-xfsettingsd---2*[{xfsettingsd}]
| |-xfwm4---2*[{xfwm4}]
| |-10*[{xfce4-session}]
|-xrdp-chansrv---{xrdp-chansrv}
```
Xorg 就是我们通常说的 xserver, 有关整个流程的调试,我们可以用下述命令进行错误排除
```shell
env LD_LIBRARY_PATH="/root/test/build/test/a/usr/lib:/root/test/build/test/a/usr/local/lib:/root/test/build/test/a/usr/lib/x86_64-linux-gnu:/root/test/build/test/a/opt/libjpeg-turbo/lib64" DBUS_SESSION_BUS_ADDRESS="unix:path=/var/run/dbus/session_bus_socket" strace -f xrdp-sesman -n
```
基本上 xrdp-sesman 会启动 Xorg ( xserver ), Xorg 会通过 tcp 或 Unix socket 与 xclient 进行通讯;还会启动 xsession, 还会启动 xrdp-chansrv从上述我们可以得知这些组件都必须启动成功否则就会看不到图像界面。我们通过 strace -f 跟踪得知 xrdp-sesman 是通过接口 execve 启动的 Xorg ,这个接口执行后,来自父进程的环境变量将会被清除,导致 LD_LIBRARY_PATH 失效,因此 Xorg 所依赖的动态库就找不到,解决方法就是把库直接拷贝到系统库的位置,就行,比如:
```shell
cp /root/smart-os/build/test/a/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0 /usr/lib/x86_64-linux-gnu/
```
# 常见问题解决方法
1. 解决 Fontconfig error: Cannot load default config file: No such file
cp /root/test/a/usr/local/etc/* /usr/local/etc/ -rf
2. 解决 Cannot read private key file /etc/xrdp/key.pem: Permission denied
```shell
adduser xrdp ssl-cert
reboot
```
3. 解决 libpango 库多版本的环境下,系统的低版本优先加载,导致 xfdesktop 不能正常启动的问题我们可以这么做
```shell
libdir=`pwd`"/a/usr"
echo "LD_LIBRARY_PATH=\"${libdir}/lib:${libdir}/local/lib:${libdir}/lib/x86_64-linux-gnu\" xfce4-session" > ~/.xsession
```
这样就可以优先加载我们编译的动态库了
4. xfce4-session 其实相应的配置也可以通过命令行工具查看
xfconf-query -c xfce4-session -p /sessions/Failsafe/Client3_Command
我们可以逐行查看每个属性,然后通过 ps -aef | grep xf* 查看相应的进程是否正确启动,如果没有启动,就会导致出现问题,然后单独手工启动那个进程,查看是什么原因导致不能正常启动的,解决问题就非常简单了。
5. xfdesktop 启动时提示Settings schema 'org.gtk.Settings.FileChooser' is not installed
方法apt install libgtk-3-common
6. xfce4 编译后,启动远程桌面,发现面板上相应的 item 都没有图标,进入文件管理器,对应的文件也没有图标,只显示文字,需要安装
方法apt install gnome-icon-theme当然这两个问题只装 libgtk-3-common 都可以解决
7. 编译 libxi 库时,会提示下面的错误,我们去官方网站去看 发现 inputproto 项目已经被废弃,怎么办?
```shell
configure: error: Package requirements (xproto >= 7.0.13 x11 >= 1.6 xextproto >= 7.0.3 xext >= 1.0.99.1 inputproto >= 2.3.99.1) were not met:
Requested 'inputproto >= 2.3.99.1' but version of InputProto is 2.3.2
```
方法其实现在这些inputproto都被合并到项目 xorgproto 里面了,编译这个库就行了,这个问题折腾我好久
8. 编译 libx11 遇到问题
```shell
checking keysym definitions... configure: error: /usr/local/include/X11 doesn't exist or isn't a directory
```
方法: --with-keysymdefdir="${xfce_install}/usr/local/include/X11"
9. 编译 pciaccess, libxcb-util 遇到问题
```shell
error: must install xorg-macros 1.8 or later before running autoconf/autogen
error: must install xorg-macros 1.16.0 or later before running autoconf/autogen
```
方法: 原因就是 aclocal 的路径设置的不完全
```shell
export ACLOCAL="aclocal -I /usr/share/aclocal -I ${xfce_share}/aclocal -I ${xfce_loc_share}/aclocal"
```
10. 我们利用 xrdp 远程访问 xfce 桌面黑屏,查看日志 .xsession-errors发现提示下述错误
```shell
(xfce4-session:1904): xfce4-session-WARNING **: 11:23:52.330: ICE connection 0x55b030d772e0 rejected
(xfwm4:1942): xfwm4-WARNING **: 11:23:52.330: Failed to connect to session manager: Failed to connect to the session manager: Authentication Rejected, reason : None of the authentication protocols specified are supported and host-based authentication failed
(xfce4-session:1904): xfce4-session-WARNING **: 11:24:00.217: ICE connection 0x55b030ddb520 rejected
Failed to connect to session manager: Failed to connect to the session manager: Authentication Rejected, reason : None of the authen
tication protocols specified are supported and host-based authentication failed
```
我们进一步追踪journalctl -xf
```shell
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[INFO ] Using default X.509 key file: /etc/xrdp/key.pem
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[ERROR] Cannot read private key file /etc/xrdp/key.pem: Permission denied
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[DEBUG] TLSv1.2 enabled
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[DEBUG] TLSv1.1 enabled
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[DEBUG] TLSv1 enabled
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[DEBUG] Security layer: requested 11, selected 0
Aug 28 11:30:52 freeabc xrdp[2172]: (2172)(139849385854784)[DEBUG] Closed socket 12 (AF_INET6 ::ffff:192.168.1.101 port 3389)
Aug 28 11:30:52 freeabc xrdp[1289]: (1289)(139849385854784)[INFO ] Socket 12: AF_INET6 connection received from ::ffff:192.168.1.105 port 11281
Aug 28 11:30:52 freeabc xrdp[1289]: (1289)(139849385854784)[DEBUG] Closed socket 12 (AF_INET6 ::ffff:192.168.1.101 port 3389)
Aug 28 11:30:52 freeabc xrdp[2173]: (2173)(139849385854784)[DEBUG] Closed socket 11 (AF_INET6 :: port 3389)
Aug 28 11:30:52 freeabc xrdp[2173]: (2173)(139849385854784)[INFO ] Using default X.509 certificate: /etc/xrdp/cert.pem
Aug 28 11:30:52 freeabc xrdp[2173]: (2173)(139849385854784)[INFO ] Using default X.509 key file: /etc/xrdp/key.pem
Aug 28 11:30:52 freeabc xrdp[2173]: (2173)(139849385854784)[ERROR] Cannot read private key file /etc/xrdp/key.pem: Permission denied
```
我们看到是 key.pem 的权限不允许导致的, sudo adduser xrdp ssl-cert 重启系统,这个问题解决
11. 如果我们运行 xsession 提示 Can't open display 即使我们设置环境变量 export DISPLAY=:10 ,也是这个提示,引起这个问题的原因有很多,但我们首先第一步要做的是要检查 Xorg( xserver ) 服务在不在,一般情况通常会忽略这个检查
12. Xorgxserver 启动时,提示错误
```shell
Using system config directory "/usr/local/share/X11/xorg.conf.d"
MESA-LOADER: failed to open vmwgfx (search paths /usr/lib/x86_64-linux-gnu/dri)
failed to load driver: vmwgfx
MESA-LOADER: failed to open kms_swrast (search paths /usr/lib/x86_64-linux-gnu/dri)
failed to load driver: kms_swrast
MESA-LOADER: failed to open swrast (search paths /usr/lib/x86_64-linux-gnu/dri)
failed to load swrast driver
couldn't get display device
```
解决:缺失显卡驱动
apt install libgl1-mesa-dri
13. Xorgxserver启动时提示错误
```shell
XKB: Failed to compile keymap
Keyboard initialization failed. This could be a missing or incorrect setup of xkeyboard-config.
(EE)
Fatal server error:
(EE) Failed to activate virtual core keyboard: 2(EE)
(EE)
```
解决:
ln -s /usr/share/X11/xkb /usr/local/share/X11/xkb
这样再运行 Xorg 就可以正常运行了。
14. failed to load driver: swrast
```shell
LD_LIBRARY_PATH="/root/smart-os/build/test/a/usr/lib:/root/smart-os/build/test/a/usr/local/lib:/root/smart-os/build/test/a/usr/lib/x86_64-linux-gnu:/root/smart-os/build/test/a/opt/libjpeg-turbo/lib64" xfwm4
MESA-LOADER: failed to open swrast (search paths /usr/lib/x86_64-linux-gnu/dri)
libGL error: failed to load driver: swrast
```
解决:
apt install libgl1-mesa-dri
15. 我们的 upower.service 运行依赖我们编译的 glib 库,系统自带的 glib 版本有点低,我们为 systemd 的服务单元增加环境变量,才能让 unit 正确运行
因此我们需要编辑 vi /lib/systemd/system/upower.service
```shell
[Service]
Type=dbus
BusName=org.freedesktop.UPower
ExecStart=/usr/libexec/upowerd
Restart=on-failure
Environment="LD_LIBRARY_PATH=/root/smart-os/build/test/a/usr/lib:/root/smart-os/build/test/a/usr/local/lib:/root/smart-os/build/test/a/usr/lib/x86_64-linux-gnu:/root/smart-os/build/test/a/opt/libjpeg-turbo/lib64"
```
16. 通过 systemctl start upower.service ,启动会被系统强杀 SIGSYS ( syscall=12 )apport.log 会提示下面的错误
```shell
ERROR: apport (pid 3268) Thu Sep 15 10:25:01 2022: host pid 3257 crashed in a separate mount namespace, ignoring
```
journalctl -xf 会提示下面的错误
```shell
Sep 15 10:25:01 freeabc kernel: [ 5505.813250] audit: type=1326 audit(1663237501.505:66): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=3300 comm="upowerd"
exe="/usr/local/bin/upowerd" sig=31 arch=c000003e syscall=12 compat=0 ip=0x7f40bfa9c0a9 code=0x0
```
单独执行 /usr/libexec/upowerd -v ,也能成功执行。这个问题让我困惑了好久,目前找到解决方法了;我们需要做的是把 upower.service 里面的几句话注释掉即可
```shell
# System call interfaces
LockPersonality=yes
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=ioprio_get
```
猜测这样可能就不会启动 seccomp 的功能了upower.service 调用的系统调用就能正确进行了,保证 systemctl start upower.service 启动成功
17. 如果采用高版本的 glibc 库mk_xfce4.sh 的编译就会出现很多问题,编译 harfbuzzgdk-pixbuf 都会遇到问题: linking of temporary binary faileddied with <Signals.SIGSEGV: 11>,目前采用降低 glibc ( 2.32 ---> 2.27 ) 版本的方法,编译通过
18. 编译 llvm 时,对内存要求特别高,小内存会导致编译失败,现象就是被系统 kill
```shell
collect2: fatal error: ld terminated with signal 9 [Killed]
```
所以一定保持系统的内存 >= 8G

BIN
xfce4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

57
初识 initramfs .md Normal file
View File

@ -0,0 +1,57 @@
# 简述
下述资料,大部分都是采摘于网上对应的博客,感觉内容不错,简单做了一下归纳,感谢大拿们的精彩分享!
内核启动时,并没加载根文件系统,有些是内核启动阶段不易完成的工作(驱动现在和内核很多都是分开的,位于外存储系统上,所以内核启动后很多事情都做不了),还有些根文件系统是加密的,反正有多种限制和需求。
所以内核启动后会先启动一个内存模式的根文件系统,通常就是 initramfs ,早期一般都是采用 initrd initrd 是一个位于内存中的完整模拟的块设备,需要整个文件系统的开销,有固定的大小,不灵活,它是一个真
实的,静态的设备,消耗 Linux 内核中的缓存和文件分页,带来更多的内存开销. 鉴于 initrd 存在很多弊端,后续逐步被 initramfs 所代替. initramfs 不是设备,而是能直接运行在内存中的根文件系统,规避了 initrd
的弊端,好处大大的。
### 为什么驱动不集成到内核?
1. Linux 是一个通用的系统,目标是针对各种不同的硬件平台,况且还有很多新的设备源源不断的出来并集成到内核,将所有的驱动全部集成到内核非常不合理,因此需要把驱动和内核解耦分开,通常这些驱动模块编译成模块,存在外部的根文件系统中
2. 根文件系统不可能在一个简单的硬盘上,当使用磁盘阵列 RAID 时根文件系统可能跨几个存储设备根文件系统也可能在某个网络设备上比如NFS ,还需要网络配置,网络认证,还有加解密的需要,等各种需求场景
为了解决这些问题initramfs 横空出世initramfs 是一个临时的文件系统,其中包含了必要的设备如硬盘、网卡、文件系统等的驱动以及加载驱动的工具及其运行环境,比如基本的 C 库,动态库的链接加载器等等
早期的处理时基于 initrd initrd 是基于 ramdisk 技术的,而 ramdisk 就是一个基于内存的块设备,因此 initrd 也具有块设备的一切属性。比如 initrd 容量是固定的,一旦创建 initrd 时设定了一个大小,就不能再进行动态调整,所以后续被 initramfs 逐步代替
# initramfs 的好处
我们知道 Linux 存在着 live 版本live 启动后会卸载光盘,把系统加载到内存中,这样尝试一个新系统或对另一个系统进行修复时不会伤害到已安装的系统,非常方便。
此外还可以
1. 加载模块,如第三方驱动
2. 定制化启动系统
3. 制作一个很小的 rescue shell
4. 内核不能,但是用户态可以完成的命令
5. 逻辑卷管理器
6. 软件 RAID
7. 蓝牙驱动
# initramfs 的组成
内核挂载 initramfs 时,文件系统的根分区并没挂载,所以无法访问文件系统中的文件。所以 initramfs 至少包含一个文件 /init ,内核的第一个进程,就是咱们常常听说的大名鼎鼎的 init 进程。
别的根据需要定制,当然 /usr, /bin 等目录也是必要的。initramfs 是通过 cpio 进行归档的,能够兼容大部分设备。
# initramfs 的运行
initramfs 通常和内核一起存储bootloader 引导内核时,通常会把 initramfs 以参数的形式传递给内核,内核检测到 initramfs ,会创建一个 tmpfs 文件系统,并把 initramfs 解压到 tmpfs 中,内核启动 tmpfs 文件系统中的 init 脚本,该程序将探测硬件设备、加载驱动,挂载真正的文件系统,执行文件系统上的 /sbin/init进而切换到真正的用户空间。真正的文件系统挂载后initramfs 即完成了使命,其占用的内存也会被释放,继而进行后续的启动过程
当2.6版本的内核引导时,在挂载真正的根文件系统之前,首先将挂载一个名为 rootfs 的文件系统,并将 rootfs 的根作为虚拟文件系统目录树的总根。那么为什么要使用 rootfs 这么一个中间过程呢?原因之一还是为了解决鸡和蛋的问题。内核需要根文件系统上的驱动以及程序来驱动和挂载根文件系统,但是这些驱动和程序有可能没有编译进内核,而在根文件系统上。如果不借助第三方,内核是没有办法挂载真正的根文件系统的。而 rootfs 虽然名称为 rootfs但是并不是什么新的文件系统事实上rootfs 就是一个 ramfs只不过换了一个名称。换句话说rootfs 是在内存中的,内核不需要特殊的驱动就可以挂载 rootfs所以内核使用 rootfs 作为一个过渡的桥梁。        
在挂载了 rootfs 后,内核将 Bootloader 加载到内存中的 initramfs 中打包的文件解压到 rootfs 中而这些文件中包含了驱动以及挂载真正的根文件系统的工具内核通过加载这些驱动、使用这些工具实现了挂载真正的根文件系统。此后rootfs 也完成了历史使命被真正的根文件系统覆盖overmount。但是 rootfs 作为虚拟文件系统目录树的总根并不能被卸载。但是这没有关系前面我们已经谈到了rootfs 基于 ramfs删除其中的文件即可释放其占用的空间
1、挂载 rootfs
用于不同操作系统的文件系统其物理存储结构是不同的,但是 Linux 的虚拟文件系统通过为这些文件系统建立中间适配层,实现了 Linux 对各个文件系统的支持Linux 的虚拟文件系统将文件系统组织为树形结构。在初始化阶段,内核挂载 rootfs 文件系统虚拟文件系统从无到有rootfs 的根作为虚拟文件系统这棵大树中的第一个节点,自然成为所有后来创建的节点的祖先。也就是说,虚拟文件系统目录树的根就是 rootfs 的根本质上rootfs 就是一个 ramfs 文件系统。        
通过挂载 rootfs虚拟文件系统的根目录已经建立起来根目录已经可以容纳文件了。所以接下来内核解压 initramfs 的内容到虚拟文件系统的根中,利用 initramfs 中的内容挂载并切换到真正的根文件系统。
2、解压 initramfs 到 rootfs
在挂载了 rootfs 后,内核将 Bootloader 加载到内存中的 initramfs 中的文件解压到 rootfs 中。而这些文件中包含了驱动以及挂载真正的根文件系统的工具,内核通过加载这些驱动、使用这些工具实现挂载真正的根文件系统。
3、挂载并切换到真正的根目录
将 initramfs 成功解压后,挂载真正的根文件系统所需的驱动、程序等已经全部俱备,可以挂载真正的根文件系统了,在 grub.cfg 文件中对应的就是 root=XXX。内核将真正的根文件系统挂载到 initramfs 文件系统中的 /root 目录下。        
挂载真正的根文件系统后rootfs 中的内容已经没有保留的意义,但是并不能将 rootfs 卸载,因为 rootfs 是整个虚拟文件系统的根。因此,为了不占用内存空间,将 rootfs 中的内容(文件)释放掉即可,然后将真正的根文件系统移动到虚拟文件系统的根(即 rootfs 的根)下,最后再将进程的文件系统的 namespace 切换到真正的根文件系统。
# initramfs文件基本操作
1. 查看 initramfs
lsinitrd
2. 解压 initramfs
/usr/lib/dracut/skipcpio initramfs-3.10.0-229.el7.x86_64.img | zcat | cpio -ivd
3. 创建 initramfs
find . | cpio -o -H newc | gzip -9 > /tmp/test.img

308
计算机运作原理.md Normal file
View File

@ -0,0 +1,308 @@
# 概述
下述资料,大部分都是采摘于网上对应的博客,感觉内容不错,简单做了一下归纳,感谢大拿们的精彩分享!
有些流程是重复描述的,我没有调整,多读几次加深印象!
# 启动
启动可以分为两种,一种为冷启动,是指计算机在关机状态下按 POWER 键启动,又叫硬件启动,比如开机,这种启动方式在启动之前计算机处于断电状态,像内存这种需要加电维持的存储部件里面的内容都丢失了,加电开机那一刻里面的值都是随机的,操作系统会对其进行初始化。
而热启动是在加电的情况下启动,又叫软件启动,比如重启,这种启动方式在启动之前和启动之后电没断过,内存等存储部件里面的值不会改变,但毕竟是启动过程,操作系统会对其进行初始化
不论是哪种启动,都会向 CPU 发送启动的信号然后开始启动。同第一篇文章我们分五个大的步骤讲述启动BIOS -> MBR -> Bootloader -> OS -> Multiprocessor
系统 BIOS 所在的 ROM 是被设计成 CPU 可直接寻址的,而且地址范围也是固定的,从 0xF0000H 至 0xFFFFFH 共 64 KB。PC 按通电源后,电源设备开始向主板和其他设备供电,此时电压还不太稳定,主板上的控制芯片组会向 CPU 发出并保持一个 RESET重置信号让 CPU 内部自动恢复到初始状态,但 CPU 在此刻不会马上执行指令。当芯片组检测到电源已经开始稳定供电了(当然从不稳定到稳定的过程只是一瞬间的事情),它便撤去 RESET 信号(如果是手工按下计算机面板上的 Reset 按钮来重启机器,那么松开该按钮时芯片组就会撤去 RESET 信号CPU 进行重置IP 寄存器的值设成 0CS寄存器的值设成 0xFFFF。也就是说 CPU 马上从地址 0xFFFF0H 处开始执行指令,这个地址在系统 BIOS 空间的地址范围内CPU 就是从这个固定的地址开始执行 BIOS 程序的。
各厂家的 BIOS 程序不尽相同,但基本都是完成 POST 自检及本地设备的枚举和初始化,包括对硬件执行一系列的测试,用来检测现在都有什么设备以及这些设备是否能正常工作,在这个阶段中,会显示一些信息,例如 BIOS 版本号等;初始化硬件设备,这个阶段在现代基于 PCI 的体系结构中相当重要,因为它可以保证所有的硬件设备操作不会引起 IRQ 线与 I/O 端口的冲突,在本阶段的最后,会显示系统中所安装的所有 PCI 设备的一个列表等。
BIOS 自检和初始化完成后,开始执行 BIOS 引导程序。由于系统 BIOS 空间只有 64KB 大小,把 Linux 内核放在这个空间里让 BIOS 引导程序直接引导是不可能的,只能把内核放在硬盘里(或其他设备,如 USB 或网络上, BIOS 根据启动顺序的设置依次查找),然后再从硬盘里引导 Linux 内核。但是,这时系统还处于实模式中,寻址能力只有 1MB没有硬盘上的文件系统等信息不会直接的引导整个 Linux 内核,而是通过先载入一个引导装入程序,然后由这个引导装入程序来引导 Linux 内核。
引导装入程序通常放在第一块硬盘(或其他设备)的第一个扇区里,这个扇区就是主引导扇区,包括硬盘主引导记录 MBRMaster Boot Record、分区表DPTDisk Partition Table及主引导扇区标志 “55AA”共 512 个字节。系统 BIOS 引导程序的唯一任务就是把存放在 MBR 中的引导装入程序载入内存的 0x7C00 位置(可以通过 BIOS 中断方式 INT 13h 读取磁盘指定扇区的内容),然后 CPU 跳转到这个地址把控制权交给引导装入程序继续引导系统。GRUBGRand Unified Bootloader就是这样的一个引导程序。
# BIOS
启动的瞬间会将寄存器 CS 和 IP 初始化CS = 0xf000, IP = 0xfff0。
刚启动的时候正处于实模式,实模式下地址总线只用了 20 位,只有 2^20 = 1M 的寻址空间,也就是只用到的内存的低 1M 这个时候分页机制还没有建立起来CPU 运行时的地址都是实际的物理地址。
但实模式下寄存器只用到了 16 位寄存器,如何使用寄存器来寻址 20 位的地址空间Intel 采用分段的机制来访问内存,也就是采用 段基址 :段偏移,
"地址 = 段基址 + 偏移量"的方式来访问,但是实模式下的寄存器只能使用 16 位,所以规定实模式下 "地址 = 段基址 X 16 + 偏移量" 。
因此根据 CS = 0xf000, IP = 0xfff0得到的 address = 0xf000 << 4 + 0xfff0 = 0xffff0
这个地址是啥? 来看内存低 1M 的内存布局:
| 起始 | 结束 | 大小 | 用途 |
| --- | --- | --- | --- |
| FFFF0 | FFFFF | 16B | BIOS 入口地址,此地址也属于 BIOS 代码,同样属于顶部的 640 KB 字节,只是为了强调 其入口地址才单独贴出来。此处 16 字节的内容时跳转指令 jmp f000:e05b |
| F0000 | FFFEF | 64KB-16B | 系统 BIOS 范围是 F0000~FFFFF 共 640KB为了说明入口地址将最上面的 16 字节从此处去掉了,所以此处的终止地址是 0xFFFEF |
| C8000 | EFFFF | 160KB | 映射硬件适配器的 ROM 或内存映射模式 I/O |
| C0000 | C7FFF | 32KB | 显示适配器 BIOS |
| B8000 | BFFFF | 32KB | 用于文本模式显示适配器 |
| B0000 | B7FFF | 32KB | 用于黑白显示适配器 |
| A0000 | AFFFF | 64KB | 用于彩色显示适配器 |
| 9FC00 | 9FFFF | 1KB | EBDA (Extended BIOS Data Area) 扩展 BIOS 数据区 |
| 7E00 | 9FBFF | 622080B 约 608KB | 可用区域 |
| 7C00 | 7DFF | 512B | MBR 被 BIOS 加载到此处,共 512 字节 |
| 500 | 7BFF | 30464B 约 30KB | 可用区域 |
| 400 | 4FF | 256B | BIOS Data Area( BIOS 数据区 ) |
| 000 | 3FF | 1KB | Interrupt Vector Table ( 中断向量表 ) |
看最上面两行,可以知道 0xffff0 地址上存放的是一个跳转指令CPU 执行这个命令然后跳转到 BIOS 代码的主体部分BIOS 主要做一下几件事:
* 自检,然后对一些硬件设备做简单的初始化
* 构建中断向量表加载中断服务程序
* 将硬盘(通常引导设备就是硬盘)最开始那个扇区 MBR 加载到
# MBR
关于 MBR(Master Boot Record),我在捋一捋磁盘及分区一文讲的比较详细了,这里不赘述,简单再说一下 MBR 的结构:
1. 引导程序和一些参数446 字节
2. 分区表 DPT64字节
3. 结尾标记签名0x55 和 0xaa两字节
MBR 的代码在分区表中寻找可以引导存在操作系统的分区,也就是寻找标记为 0x80 的活动分区,然后加载该活动分区的引导块,再执行其中的操作系统引导程序 Bootloader。
# Bootloader
Bootloader操作系统引导程序操作系统加载器不论怎么叫它的主要作用就是将操作系统加载到内存里面。操作系统也是一个程序需要加载到内存里面才能运行。平常正在运行的计算机我们可以使用 exec 族函数来加载运行一个程序,同样的要加载运行操作系统这个程序就使用 Bootloader。
在 Bootloader 里面还做了一些其他事情,比如进入保护模式,开启分页机制,建立内存的映射等等。像 GRUBU-Boot 等都属于 Bootloader只是功能更多更强大。
# GRUB引导过程
GRUBGRand Unified Bootloader是一个多重启动管理器。它可以在多个操作系统共存时选择启动哪个系统可以启动的操作系统包括Linux, FreeBSD, Solaris, NetBSD, BeOS, OS/2, Windows 95/98 /NT /2000。它可以载入操作系统的内核和初始化操作系统如Linux, FreeBSD或者把启动权交给操作系统如Windows 98来完成启动。
GRUB 的实质是一个 mini os它拥有 shell支持 script支持特定文件系统等。GRUB 由 stage1stage1_5stage2 以及 /boot/grub 目录下的诸多文件包括Grub的配置文件与相关文件系统定义文件等组成。
stage1 被编译成了一个 512 字节的 img写在硬盘的 0 面 0 道第 1 扇,它所做的唯一的事情就是装载第二引导装载程序 stage2。
stage1_5 写进了 MBR 后的 15 个扇区中(因为 e2fs_stage1_5 大小为 7.5k)。硬盘上第一个文件系统分区的开始扇区最小也只能从 0 柱面1 磁头1 扇区开始。就是说 MBR 所在 0 磁头就只用到了 1 个扇区而已(其它扇区都是未用的,不属于任何分区),按照现在硬盘的规格来说,一般一个柱面磁头都有 60+ 个扇区,所有将 stage1_5 写进 MBR 以后的扇区中不会影响正常的文件系统分区。stage1_5 就是文件系统的解释代码,根据 /boot分区或/boot所在分区的具体文件系统类型而异ext3 分区的话就是 e2fs_stage1_5。在 stage1_5 没有被加载以前,系统无法识别任何文件系统(但是可以通过 BIOS 中断方式 INT 13h 读取磁盘指定扇区的内容), 加载 stage1_5 以后就可以识别 /boot所在分区的文件系统了从而为加载 stage2 作好了准备。
stage2 是 grub 最核心的部分有 100 多KB所以只能放在文件系统中放在 /boot 分区里,放在这里的通常还有 Linux 内核映像文件。加载 stage2 后 grub 会根据 menulist 或用户输入加载 Linux 内核映像文件,即将内核映像装入地址 0x90000 的内存中,将内核入口装入到地址 0x90200 的内存中,然后跳转到内核入口处开始启动内核。
# OS
操作系统内核加载到内存之后,就做一些初始化工作建立好工作环境,比如各个硬件的初始化,重新设置 GDTIDT 等等初始的操作。初始化启动其他处理器(如果有多个处理器的话)。这里不细说,也不好叙述,等下面直接看实例 xv6 做了哪些事,怎么做的。
# Multiprocessor
上述的启动过程是单处理情况下的启动过程,多处理器的情况下有些不同,用一句话先来简单概括多处理器情况下的启动:先启动一个 CPU用它作为基础启动其他的处理器。
先启动的这个 CPU 称作 BSP(BootStrap Processor),其他处理器叫做 AP(Application Processor)。BSP 是由系统硬件或者 BIOS 动态选择决定的。
多处理器启动过程大致分为以下几个大步骤:
1. BIOS 启动 BSP流程与上述讲的 BIOS-MBR-bootloader-OS 差不多
2. BSP 从 MP Configuration Table 中获取多处理器的的配置信息
3. BSP 启动 APs通过发送 INIT-SIPI-SIPI 消息给 APs
4. APs 启动,各个 APs 处理器要像 BSP 一样建立自己的一些机制,比如保护模式,分页,中断等等
这里我们主要关注第二点,获取多处理器的配置信息
# BSP启动详解
1. 在 BIOS POST 阶段BSP 创建了 ACPI 表并添加它的 initial APIC ID。
2. 进到 OS 后,内核最开始的代码还是由 BSP 执行,初始化后进入正式的 SMP Boot 流程。
3. 在 BSP 执行后,将 processor 设置为 CPU 0 并广播一条 SIPI 消息给其他 APSIPI 消息包含了 BIOS AP 初始化的代码地址。
4. 第一个获得 SIPI 消息的 AP 获取 BIOS 初始化信号量,执行初始化代码,添加 APIC ID 并将 processor 加1初始化结束后AP 执行 CLI (Clear Interrupt Flag) 指令并 halt 自己。
5. 所有的 AP 都执行完初始化后BSP 通过系统总线获取 processors 数量后,开始执行 OS boot-strap code、start-up code。AP 现在只能对 INITs, NMIs, and SMIs 响应,当然也响应 STPCLK# 引脚的 snoops、assertions
用一句话来概括多处理器情况下的启动:先启动一个 CPU再以它为基础启动其他的处理器。
先启动的这个 CPU 称作 BSP(BootStrap Processor),其他处理器叫做 AP(Application Processor)。硬件会动态选择系统总线上的一个 processor 作为 BSP其余的为 AP。在计算机上电或者重置系统时每个 CPU 都先执行处理器自检BIST自检通过的CPU就拥有了称为 BSP 的资格,那么此时选谁呢?
选择的方式为上电后所有的 CPU 都执行 NOP 指令,看看哪个 CPU 先发送了 NOP就会成为 BSPBSP 选出来之后,它会将 IA32_APIC_BASE MSR 里面的 BSP flag 设置为1标识该处理器是 BSP其他的APs进入 wait for SIPI 的状态,等待 BSP 的发号施令。
在 BIOS 中BSP 首先要收集所有的 AP 信息,将所有 AP 信息登记下来,这个登记表称为 MP Configuration Table它首先把自己加进去CPU 0然后让 APs 自己在登记表上登记。Processors 之间传递消息靠的是一种叫 Inter-Processor InterruptIPI的机制而通知登记在它们的语言里就是 SIPI(Start-up IPI ),当然 SIPI 只能由 BSP 来说才管用。
通常BSP的初始化顺序为
1. 初始化内存。
2. 加载microcode
3. 初始化MTRRs
4. 初始化Cache
5. 加载 AP start-up code 到 1Mbyte 以下的 4K 内存中。
6. Enable APIC (SVR bit8
7. Program ICR寄存器把AP start-up code地址写到该寄存器
8. 在AP start-up code里,每个AP将会增加一个COUNT变量表示AP已经起来了
9. 广播INIT-SIPI-SIPI IPI sequence to the Aps,这时所有的AP才会真正被唤醒起来执行
https://zhuanlan.zhihu.com/p/598552628
https://peterhu.github.io/posts/2020/08/19/CPU%E5%A4%9A%E6%A0%B8%E5%88%9D%E5%A7%8B%E5%8C%96.html
# UP
UPUni-Processor系统只有一个处理器单元即单核CPU系统。
# SMP
对称多处理器结构 , 英文名称为 " Symmetrical Multi-Processing " , 简称 SMP 。
SMP 又称为 UMA , 全称 " Uniform Memory Access " , 中文名称 " 统一内存访问架构 " 。
在 " 对称多处理器结构 " 的 系统中 , 所有的处理器单元的地位都是平等的 , 一般指的是服务器设备上 , 运行的 多个 CPU , 没有 主次/从属 关系,都是平等的。
这些处理器 共享 所有的设备资源 , 所有的资源对处理器单元具有相同的可访问性 , 如 : 磁盘 , 内存 , 总线等 多个CPU处理器共享相同的物理内存 , 每个 CPU 访问相同的物理地址 , 所消耗的时间是相同的 ;
要注意这里提到的“处理器单元”是指“logic CPU”而不是“physical CPU”。举个例子如果一个“physical CPU”包含2个core并且一个core包含2个hardware thread。则一个“处理器单元”就是一个hardware thread。
# 内核针对多处理器 CPU 下的调度
BIOS 调入执行启动引导区程序后,这段程序录入 Linux 操作系统的启动部分,解压缩 Linux 内核核心映像,然后转入 start_kernel 函数开始执行。在这以前,系统没有对 AP 做任何处理。在 start_kernel 函数中,主要处理例如 cache、内存等初始化工作最后要调用 smp_init 函数,在这个函数里,具体实现 SMP 系统各 CPU 的初始处理机制, 我们来分析 smp_init 函数
在 [linux/init/main.c] 中
~~~c
static void __init smp_init(void)
{
smp_boot_cpus();
smp_threads_ready=1;
smp_commence();
}
~~~
在函数 smp_boot_cpus 中,要建立并初始化各 AP关键代码如下
在 [linux/arch/i386/kernel/smpboot.c] 中
~~~C
void __init smp_boot_cpus(void)
{
……
for (apicid = 0; apicid < NR_CPUS; apicid++) {
if (apicid == boot_cpu_id)
continue; // 是BP因为上面已经初始化完毕就不再需要初始化
if (!(phys_cpu_present_map & (1 << apicid)))
continue; // 如果CPU不存在不需要初始化
if ((max_cpus >= 0) && (max_cpus <= cpucount+1))
continue; //如果超过最大支持范围,不需要初始化
do_boot_cpu(apicid);// 对每个AP调用do_boot_cpu函数
……
}
……
}
~~~
下面我们看一下do_boot_cpu中做了什么工作
在[linux/arch/i386/kernel/smpboot.c]中
~~~c
static void __init do_boot_cpu (int apicid)
{
struct task_struct *idle; // 空闲进程结构
……
if (fork_by_hand() < 0) //在每个cpu上建立0号进程这些进程共享内存
……
idle->thread.eip = (unsigned long) start_secondary;
// 将空闲进程结构的eip设置为 start_secondary 函数的入口处
……
start_eip = setup_trampoline(); // 得到trampoline.S代码的入口地址
stack_start.esp = (void *) (1024 + PAGE_SIZE + (char *)idle);
……
*((volatile unsigned short *) phys_to_virt(0x469)) = start_eip >> 4;
Dprintk("2.\n");
*((volatile unsigned short *) phys_to_virt(0x467)) = start_eip & 0xf;
Dprintk("3.\n");
// 将trampoline.S的入口地址写入热启动的中断向量(warm reset vector)40:67
……
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
// 确定发送对象
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
// 发送INIT IPI
……
apic_write_around(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
//确定发送对象
apic_write_around(APIC_ICR, APIC_DM_STARTUP | (start_eip >> 12));
//发送STARTUP IPI
……
}
~~~
现在对上面初始设置做如下概括 [1]
BSP 将 AP 在一开始被唤醒后需要执行的代码trampoline.S的首地址写入热启动向量warm reset vector
即从40:67开始的两个字。这样当 BSP 对 AP 发送 IPI 时AP 响应中断,自动跳入这个 trampoline.S 代码
部分继续执行。为了 AP 有足够的时间响应中断BSP 在发送中断请求后要延迟一段时间,。
在这以后,事实上 AP 已经在工作了,我们跟随 AP看它在做什么。AP 响应中断直接跳转至 trampoline.S 的
入口处trampoline.S 在载入符号表 (gdt) 和局部符号表 (ldt) 之后进入保护模式并跳至 head.S 的入口处:
在 [linux/arch/i386/kernel/trampoline.S] 中
~~~C
……
inc %ax #protected mode (PE) bit
lmsw %ax # 进入保护模式
jmp flush_instr
flush_instr:
ljmpl $__KERNEL_CS, $0x00100000
# 一个长跳转0x10:0x00100000是内核被解压后的起始地址即 head.S 的 startup_32[7]
……
~~~
AP 转入 head.S 继续执行,但是执行的代码与 BSP 所执行的并不完全一致:
在 [linux/arch/i386/kernel/head.S] 中
~~~C
ENTRY(stext)
ENTRY(_stext)
startup_32:
……
incb ready # 该段代码每执行一次ready 值加 1BSP 执行时 ready 的值从 0 变为 1
……
movb ready, %cl
cmpb $1,%cl
je 1f # 当执行 CPU 为 BSP 时ready 的值为 1
call SYMBOL_NAME(initialize_secondary) # 执行 initialize_secondary 函数
jmp L6
1:
call SYMBOL_NAME(start_kernel) # 执行 start_kernel() 函数
L6:
jmp L6
ready: .byte 0 # ready 为字节变量,初始值为 0
~~~
AP 执行 head.S 的过程是当执行到上述代码的时候,由于 ready 的值被改变,不再等于 1所以就继续向前执行
,调用 initialize_secondary 函数,而不是像 BSP 一样执行标号 1 处的代码调用start_kernel函数
initialize_secondary 函数里面的代码很简单:
在 [linux/arch/i386/kernel/smpboot.c] 中
~~~c
void __init initialize_secondary(void)
{
asm volatile(
"movl %0,%%esp\n\t"
"jmp *%1"
:
:"r" (current->thread.esp),"r" (current->thread.eip));
}
~~~
这是一段内嵌汇编程序,将程序跳转至 current->thread.esp即前面的idle->thread.esp处 [8]。CPU执
行 start_secondary 函数,进入空闲状态。
在 [linux/arch/i386/kernel/smpboot.c] 中
~~~c
int __init start_secondary(void *unused)
{
cpu_init();
smp_callin();
while (!atomic_read(&smp_commenced))
rep_nop();
local_flush_tlb();
return cpu_idle(); // 进入空闲进程
}
~~~
至此,一个 AP 的初始化过程就完成了。
总结
下面简要的再把Linux的SMP启动过程做一总结。
在 SMP 中,首先要对各个处理器进行初始化。然后 BSP 工作,而其它的 CPUAP则停留在一个初始化好的
中断屏蔽状态休眠。BSP 继续进行启动过程,在执行到操作系统的 start_kernel 之前BSP 所进行的工作与单
处理器系统所做的工作是相同的。在 start_kernel 中BSP 通过 smp_init 对每个 AP 进行初始化。初始化的
方式是通过 APIC 发送 IPI。当 BSP 初始化完毕所有的 AP 之后,就继续执行 start_kernel 中的其余部分代码。
而 AP 在接收到 IPI 之后,跳转到事先设置好的地址处执行 trampoline.S 和 head.S。在执行 head.S 的过程中
直接跳入事先创建好的空闲进程,进入空闲状态,等待以后的系统调度。
内核调度
在 [kernel/sched.c] 中, 内核为每一颗 CPU 分配了一个 runqueue ,我们的线程驱动就是每个 CPU 调用此队列的任务进行执行驱动
# 内核是怎么知道各个硬件的信息的?
答案就是通过 SMBios 表,此表由 UEFI 或者 Legacy BIOS 提供的, 从 SMBIOS 的 spec 中可以看到,对于基于 Legacy BIOS 的系统而言,系统软件可以通过在物理内存范围 000F0000h 000FFFFFh 内搜索制定的字符串来定位到 SMBIOS 表的入口点。对于SMBIOS 2.1 而言,这个字符串是 "_SM_",对于 SMBIOS 3.0 而言,这个字符串为 "_SM3_"。
而对于基于 UEFI 的系统而言EFI configuration table (EFI_CONFIGURATION_TABLE) 包含了指向 SMBIOS table 的指针。
每个硬件方法不同。比如说内存,内存条上有一个 smbus 总线的 eeprom记录内存条的信息。usb 总线的总线协议就规定了设备类型如存储设备输入设备等。pcie 总线有 vendor id, device id. 板上一些无法通过枚举过程识别的,可能会硬编码在 BIOS 里,因为每个主板都要研发一次 BIOS。BIOS 和内核传递信息有多种标准。acpi, device tree 之类的。有些设备内核还会自己枚举,不用 BIOS 告诉他。
# 内核线程的实现
https://segmentfault.com/a/1190000040253849
# 锁的实现
特别注意锁的悬停 ( mutex 的实现原理 )
所有的锁的机制都是类似于“自旋锁”的机制mutex 也不例外,当然会阻塞,是因为加锁失败,会把当前线程加入等待队列,把当前线程加入等待队列,等待下一轮的锁的抢占,抢占到锁,线程继续执行,否则还得继续等待,而对应的 CPU 线程,可没闲着继续驱动内核线程执行,对于用户层来说,仿佛多个线程在不停的执行。
https://segmentfault.com/a/1190000040360086