一、实验目的
- 理解操作系统生成的概念和过程;
- 理解操作系统两类用户界面(操作界面,系统调用)概念;
二、实验内容
- 在 Ubuntu 或其他 Linux 平台环境下裁剪和编译 Linux 内核,并启用新的内核。
- 在 Ubuntu 或其他 Linux 平台为 Linux 内核增加 1-3 个新的系统调用,并启用新的内核,编写一个应用程序测试新增加的系统调用是否能正确工作。
- 在 Windows 环境下,编写一个批处理程序(算命大师.bat),程序运行后,输入:出生年月日(例如 2000-07-31)。系统输出相应的属相和星座,例如:你属兔, 狮子座。要求:输入进行合法性检查,能循环接收用户的输入,直到输入 q 或Q 就退出。
三、实验过程
1)编译新内核
划重点:若Linux安装在虚拟机中,强烈建议编译内核前为虚拟机分配足够大的空间,亲测30G可能不大够。此外,强烈建议为虚拟机多分配几个处理器,防止编译安装过程耗费过长时间。
获取内核源码
-
首先使用以下命令查看版本信息:
sudo lsb_release -a //查看OS发行版本 cat /proc/version //查看当前内核版本 apt-cache search linux-source //查看适合的内核版本
如下图所示:
这里笔者选择了Linux5.0.0内核。
获取内核可到官网下载,也可选择直接在终端中下载。以终端中下载为例。以下命令均需要root权限,因而建议先使用sudo su命令进入root下。 -
在终端中输入以下命令下载源码:
apt-get install linux-source-5.0.0 //获取相应版本的内核源码
(假如在下载过程中,终端提示无法连接到服务器,建议检查虚拟机的网络连接。)
内核下载完成后,可在/usr/src目录下看到源码压缩包。接着,将内核源码解压,并放入主目录下:
命令如下:tar –xvf /usr/src/linux-source-5.0.0.tar.bz2
解压后如下图所示:
安装相关依赖
不同版本内核所需依赖可能有所差别,这里列出部分可能需要安装的依赖,后续可根据make menuconfig命令的提示再安装所需依赖。
apt-get install libncurses5-dev libssl-dev
apt-get install build-essential openssl
apt-get install minizip zlibc
apt-get install libidn11-dev libidn11
apt-get install libqt4-headers bison flex
配置内核模块和参数
-
首先把正在使用中的内核配置文件/usr/src/linux-headers-5.3.0-40-generic/.config 拷贝到linux-source-5.0.0目录下。命令如下:
cp /usr/src/linux-headers-5.3.0-40-generic/.config linux-source-5.0.0 //注意路径及版本
此时进入linux-source-5.0.0目录下,可使用以下命令查看拷贝过来的.config配置文件。
其中,ls命令可显示当前目录下的内容,ls -a命令可显示包括隐藏项在内的所有内容。 -
输入命令make menuconfig命令打开图形化界面的字符终端。
先选load,利用当前的内核配置详单来设置将要编译的内核,接着选save来保存当前设置。最后保存配置文件为.config。
编译新内核
-
清除以前编译的旧文件和中间文件。假如是第一次编译,可不执行此步骤。
make mrproper make clean
-
编译新内核,命令如下:
make -jn
n依据自己的配置来定,笔者为虚拟机分配了4个核,故使用的是make -j4。分配的核越多,该过程执行的越快。以make -j4为例,笔者在该过程耗时约50分钟。
安装模块和内核
-
安装模块。
make modules_install
-
安装新内核。
make install
启用新内核
- 终端中输入reboot命令,重启。
- 开机时长按Shift进入Ubuntu高级选项,选择新编译的内核。
- 打开终端,查看当前内核版本。
2)增加系统调用
-
安装vim
apt-get install vim
-
进入新内核目录下,添加自己的函数:
cd linux-source-5.0.0 sudo vim kernel/sys.c
如图所示:
终端中vim的使用可参考:https://blog.csdn.net/qq_37497322/article/details/78445455 -
添加函数声明:
vim arch/x86/include/asm/syscalls.h
参照已有系统调用的函数声明添加自定义函数的声明。
-
添加系统调用号:
vim arch/x86/entry/syscalls/syscall_64.tbl
如图所示:
-
编译新内核,步骤同上。(从make menuconfig开始)
-
启用新内核,测试系统调用的添加结果。
在文本编辑器中,编写代码如下(命名为test.c):#include <linux/kernel.h> #include <sys/syscall.h> #include <unistd.h> #include <stdio.h> int main(int argc,char **argv) { //548:hello() printf("System call sys_helloworld return %ld\n", syscall(548)); //549:min(int a, int b) printf("System call sys_min return %ld\n",syscall(549, 1, 2)); return 0; }
gcc编译并运行,命令及结果如下:
gcc -o test test.c ./test
输入demsg命令,查看进程信息:
3)Windows批处理程序
源码如下:
@Echo Off
:in
Set /p input=输入: 出生年月日 (例如 20000101)::接收键盘输入
Set year=%input:~0,4% ::分割字符串
Set monthday=%input:~4,4%
Set month=%input:~4,2%
Set day=%input:~6,2%
Set /a mod=%year% %% 12
Set /a "yp=!(%year% %% 4)&!(!(%year% %% 100))|!(%year% %% 400)" ::判断是否为闰年,闰年为1,平年为0
if "%input:~0,1%"=="q" goto end
if "%input:~0,1%"=="Q" goto end
if not "%input:~7,1%"=="" (
if not "%input:~8,1%"=="" (echo "输入错误") else (goto start)
) else (echo "输入错误")
call %0
:start
if "%month%" EQU "01" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "03" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "04" if "%day%" GTR "30" echo 输入错误 & goto in
if "%month%" EQU "05" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "06" if "%day%" GTR "30" echo 输入错误 & goto in
if "%month%" EQU "07" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "08" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "09" if "%day%" GTR "30" echo 输入错误 & goto in
if "%month%" EQU "10" if "%day%" GTR "31" echo 输入错误 & goto in
if "%month%" EQU "11" if "%day%" GTR "30" echo 输入错误 & goto in
if "%month%" EQU "12" if "%day%" GTR "31" echo 输入错误 & goto in
if %yp%== 0 if "%month%" EQU "02" if "%day%" GTR "28" echo 输入错误 & goto in
if %yp%== 1 if "%month%" EQU "02" if "%day%" GTR "29" echo 输入错误 & goto in
if %mod%==0 echo 属相:猴
if %mod%==1 echo 属性:鸡
if %mod%==2 echo 属相:狗
if %mod%==3 echo 属相:猪
if %mod%==4 echo 属相:鼠
if %mod%==5 echo 属相:牛
if %mod%==6 echo 属相:虎
if %mod%==7 echo 属相:兔
if %mod%==8 echo 属相:龙
if %mod%==9 echo 属相:蛇
if %mod%==10 echo 属相:马
if %mod%==11 echo 属相:羊
if "%monthday%" LEQ "0119" echo 星座:魔蝎座 & goto in
if "%monthday%" GEQ "0120" if "%monthday%" LEQ "0218" echo 星座:水瓶座 & goto in
if "%monthday%" GEQ "0219" if "%monthday%" LEQ "0320" echo 星座:双鱼座 & goto in
if "%monthday%" GEQ "0321" if "%monthday%" LEQ "0419" echo 星座:白羊座 & goto in
if "%monthday%" GEQ "0420" if "%monthday%" LEQ "0520" echo 星座:金牛座 & goto in
if "%monthday%" GEQ "0521" if "%monthday%" LEQ "0621" echo 星座:双子座 & goto in
if "%monthday%" GEQ "0622" if "%monthday%" LEQ "0722" echo 星座:巨蟹座 & goto in
if "%monthday%" GEQ "0723" if "%monthday%" LEQ "0822" echo 星座:狮子座 & goto in
if "%monthday%" GEQ "0823" if "%monthday%" LEQ "0922" echo 星座: 处女座 & goto in
if "%monthday%" GEQ "0923" if "%monthday%" LEQ "1023" echo 星座:天秤座 & goto in
if "%monthday%" GEQ "1024" if "%monthday%" LEQ "1122" echo 星座:天蝎座 & goto in
if "%monthday%" GEQ "0321" if "%monthday%" LEQ "0419" echo 星座:射手座 & goto in
if "%monthday%" GEQ "1222" echo 星座:魔蝎座 & goto in
:end
Pause
运行结果: