编译Linux kernel步骤
创建优麒麟虚拟机(若已装好可跳过)
1.下载优麒麟的镜像文件
-
官网下载:https://www.ubuntukylin.com/downloads/ (下载速度慢)
-
镜像网站:官网底部(推荐)
创建虚拟机硬件配置如下:
硬盘空间至少大于50G,否则后续编译内核会因存储空间不够而失败。
登录优麒麟后,注意一定要点击桌面的“安装“,否则试用版无法正常进行以下操作,系统重启会进行清空。
查看正在使用的内核版本,后面下载的内核版本最好不要高于目前版本
#查看版本
uname -r
虚拟机环境配置
安装编译的必要工具gcc、gdb、bison、flex、libncurses5-dev、libssl-dev、libidn11以及虚拟机的必备工具。
#安装编译所需工具
sudo apt install gcc gdb bison flex libncurses5-dev libssl-dev libidn11 build-essential
从网上下载不高于目前内核版本的kernel源代码。
- 官网:https://www.kernel.org/ (下载速度慢)
- 镜像网站:http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/(推荐)
此处下载 linux-5.4.3.tar.xz(可以自行选择其他版本) ,之后移动压缩包到 usr/src 目录下,解压后删除。
#移动压缩包到目标文件夹
sudo mv linux-5.4.3.tar.xz /usr/src
#解压缩
sudo tar -xf linux-5.4.3.tar.xz
#删除压缩包
sudo rm linux-5.4.3.tar.xz
编译安装
将目前内核的配置拷贝到新内核的源码目录下,作为新内核的配置文件。其中,需要进入配置文件.config,查看一下 .config 文件是否变化,有的版本此操作会把前面双引号内置空的内容恢复,此时需要手动删除引号中的内容。
#进入源码目录
cd /usr/src/linux-5.4.3
#拷贝
sudo cp -v /boot/config-$(uname -r) .config
#查看文件
sudo vi .config
#查看 :/CONFIG_SYSTEM_TRUSTED_KEYS
使用make menuconfig 个性化配置 —— 实际实验过程中没有修改,直接使用默认配置即可。显示如下界面后,点击 Exit – yes 即可。
sudo make menuconfig
进入源码目录,使用make命令编译内核,同时借助 -jn 加快编译速度。其中,n是要生成的作业数,通常的做法是每个处理器产生一个或两个作业,最多不超过分配总核数的两倍,可以查看虚拟机硬件配置中的处理器总分配内核数。此阶段比较耗时。
#4个作业同时进行编译
sudo make -j4
安装内核模块,进一步安装内核模块。
sudo make modules_install
模块安装完成后,进行内核安装。
sudo make install
将新安装的内核设置为引导,并更新grub引导程序。
#结尾为自己内核的版本
sudo update-initramfs -c -k 5.4.3
#更新grub
sudo update-grub
启动新内核
重启虚拟机,选择 ”高级选项——对应新内核的版本“ 进行启动,此处为5.4.3。
启动完毕后,查看目前内核版本,若为新内核版本,则启动成功。
uname -r
添加系统调用
参考文章:【HUST】网安|操作系统实验|实验一 内核编译、系统调用、编写批处理脚本
本文章在此基础上改动。
修改文件
-
系统调用:linux-5.4.3/kernel/sys.c
-
系统调用函数声明:linux-5.4.3/include/linux/syscalls.h
-
ID:linux-5.4.3/arch/x86/entry/syscalls/syscall_64.tbl
-
ID声明:linux-5.4.3/include/uapi/asm-generic/unistd.h
需要修改的代码如下:
- 系统调用:linux-5.4.3/kernel/sys.c
SYSCALL_DEFINE2(SSD_Add,int,x,int,y){
return x+y;
}
SYSCALL_DEFINE3(SSD_Max,int,a,int,b,int,c){
if(a>b) b=a;
if(b>c) c=b;
return c;
}
- 系统调用函数声明:linux-5.4.3/include/linux/syscalls.h
asmlinkage long sys_SSD_Add(int x, int y);
asmlinkage long sys_SSD_Max(int a, int b, int c);
- ID:linux-5.4.3/arch/x86/entry/syscalls/syscall_64.tbl
548 64 SSD_Add __x64_sys_SSD_Add
549 64 SSD_Max __x64_sys_SSD_Max
- ID声明:linux-5.4.3/include/uapi/asm-generic/unistd.h
#define __NR_ssd_add 548
__SYSCALL(__NR_ssd_add, sys_SSD_Add)
#define __NR_ssd_max 549
__SYSCALL(__NR_ssd_max, sys_SSD_Add)
如下图。
重新编译
与实验二基本相同,编译前清理一下上一次残留的编译文件即可。
sudo make mrproper
sudo make clean
sudo make menuconfig
sudo make -j4
sudo make modules_install
sudo make install
sudo update-initramfs -c -k 5.4.3
sudo update-grub
reboot
调用新增函数进行测试
测试文件:test.c
#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
long ret;
ret = syscall(549,1,2,3); //Max
printf("ret:%ld\n",ret);
ret = syscall(549,7,6,5); //Max
printf("ret:%ld\n",ret);
ret = syscall(548,4,6); //Add
printf("ret:%ld\n",ret);
ret = syscall(549,7,9,8); //Max
printf("ret:%ld\n",ret);
}
编译运行该文件。
sudo gcc -o test test.c
sudo ./test
输出如下图。
可能遇到的问题
-
重启时没有出现选择内核的界面?(若用ubuntu可能会出现)
修改配置文件,更换默认启动盘
详见:https://blog.youkuaiyun.com/weixin_46584887/article/details/125973263
-
undefined reference to ‘xxx’
在linux4.17以后,添加系统调用必须以
__x64_sys_
开头!!将syscall_64.tbl中的系统调用改函数名开头即可。详见:https://blog.youkuaiyun.com/qq_44765221/article/details/111087361
编写批处理程序
任务要求
要求:在 Ubuntu (或银河麒麟) 或 Windows 下,编写脚本或批处理。
功能:在指定目录中全部 txt 文件的末尾追加一行,写入用户名,日期,时间。
提示:
- 目录通过命令行的参数来指定,不要在脚本中写死;
- 注意检查文件的后缀是否 txt;
- 日期和时间的写入格式可以自己确定【例如特殊字符标识】;
- 已写有日期和时间的文件只能更新日期和时间,不能追加。
步骤
初始化
建立文件,test1.txt与test2.txt,并初始化文本文件的内容。
编写脚本
脚本文件“myshell2.sh”源代码如下,将待测试的txt文件与脚本文件放置于同一目录下,进行测试。
str_insert="#OK# $USER `date +%Y-%m-%d,%H:%M:%S`" #设置特殊标识设为#OK#,表示已写入
for ofile in $1/*.txt #用$1接收第一个命令行参数(目录);*.txt检查文件后缀是否为txt
do
if [ `grep -c "#OK#" $ofile` -eq 0 ];then
echo $str_insert >> $ofile #未写入,向文件中追加写入字符串str_insert
else
sed -i "/#OK#/c $str_insert" $ofile #已写入,用sed更新字符串
fi
done
测试运行
#第一参数"."表示选择该目录下的txt文件
./myshell2.sh .
结果:
在目标目录下的所有txt文件新增一行 “#OK# willow 2022-11-28,19:19:48”。
再次运行,不再追加新行,而是刷新变为目前时间,“#OK# willow 2022-11-28,19:23:11”。