《操作系统原理》实验一:编译新内核并为Linux内核增加系统调用
一、实验目的
1)理解操作系统生成的概念和过程
2)理解操作系统两类用户界面(操作界面,系统调用)概念
二、实验内容
1)在Unbantu或Fedora环境下裁剪和编译Linux内核,并启用新的内核。
2)在Unbantu或Fedora环境下为Linux内核增加1-3 个新的系统调用,并启用新的内核,编写一个应用程序测试新增加的系统调用是否能正确工作。
3)在windows 环境下,利用高级语言编程环境(限定为VS 环境或VC 环境)调用相关的系统调用(即系统API)实现一个包括“进程创建,文件读写”的应用程序。有一个文本文件CommandList.txt,第一行是说明性文字:本文件最后一次打开和运行日期是20190325。第二行开始每行是一个可执行程序的名称(含路径)。编写一个应用程序能打开该文件,并顺序执行其中的每个程序,并更新文件第一行中的日期。
4)在windows 环境下,编写一个批处理程序(算命大师.bat),程序运行后,输入:出生年月日(例如20000731)。系统输出你的属相和星座,例如:你属兔,狮子座。
三、实验过程
1)编译并启用新Linux内核
①任务环境
Ubuntu版本:16.04 64位
Linux内核版本:4.5.0-29-generic
新内核版本:4.11.9
②查看内核版本
③下载内核源码
内核源码下载自kernel.org镜像站,使用4.11.9稳定版
④下载完成后解压
⑤安装基本的编译工具
命令列表:
sudo apt-get install libncurses5-dev libssl-dev
sudo apt-get install build-essential openssl
sudo apt-get install zlibc minizip
sudo apt-get install libidn11-dev libidn11
⑥在内核源码的目录中打开终端,依次执行:
sudo make mrproper
sudo make clean
sudo make menuconfig
⑦直接按右方向键选择到exit退出,退出提示中选择保存,实现内核的默认配置
⑧执行命令sudo make –j8
j后面跟的参数是电脑cpu的进程数,我的电脑是四核八线程的,所以执行-j8,8个线程并行编译,编译速度是普通make命令的8倍。这一步通常要等比较长时间等它执行完
⑨sudo make –j8过程
⑩执行sudo make modules_install,安装内核模块
⑪执行sudo make install,安装内核
⑫重启电脑,在Ubuntu高级选项中选用新内核
⑬检查新内核版本
2)为Linux内核增加新的系统调用
①修改内核代码:内核解压后打开/arch/x86/entry/syscalls/syscall_64.tbl,设置系统调用号333
②修改内核代码:打开/include/linux/syscalls.h,即系统调用的头文件,添加函数声明
③修改内核代码:打开第三个/kernel/sys.c,定义系统调用
④sudo make menuconfig
⑤直接按右方向键选择到exit退出,退出提示中选择保存,实现内核的默认配置
⑥执行命令sudo make –j8
j后面跟的参数是电脑cpu的进程数,我的电脑是四核八线程的,所以执行-j8,8个线程并行编译,编译速度是普通make命令的8倍。这一步通常要等比较长时间等它执行完
⑦sudo make –j8过程
⑧执行sudo make modules_install,安装内核模块
⑨执行sudo make install,安装内核
⑩重启电脑,在Ubuntu高级选项中选用新内核
⑪编写一个C语言文件
⑫gcc a.c编译上面的 .C文件,再输入./a.out输出编译结果,结果是1
⑬在终端中输入命令dmesg,查看系统日志发现,在最后出现了“Hello,U201717126!”,表明添加系统调用成功
3)实现进程创建、文件读写
任务环境:Windows 10 x64 + Visual Studio 2017 Enterprise
代码实现:
#define _CRT_SECURE_NO_WARNINGS //忽略安全检查错误
#define _CRT_NONSTDC_NO_DEPRECATE
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <time.h>
#include <string.h>
void create(char process[]) {
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = TRUE;
BOOL bRet = CreateProcess(NULL, process, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
}
int main()
{
char timeContent[100] = { 0 };
char readBuffer[1000] = { 0 };
char commandName[10][100] = { 0 }; //按行分开的命令
int num = 0; //命令个数
DWORD dwRead = 0;
DWORD dwWrite = 0;
HANDLE hFile = CreateFile("./commandList.txt", GENERIC_WRITE | GENERIC_READ, 0,
NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile failed!");
CloseHandle(hFile);
return -1;
}
//获取时间
time_t t;
struct tm * lt;
char mon[10];
char tmp[10];
time(&t);//获取时间戳
lt = localtime(&t);//转为时间结构
if (lt->tm_mon % 10<10) {
strcpy(mon, "0");
itoa(lt->tm_mon + 1, tmp, 10);
strcat(mon, tmp);
}
char year[10];
itoa(lt->tm_year + 1900, year, 10);
char day[10];
itoa(lt->tm_mday, day, 10);
char date[10];
strcpy(date, year);
strcat(date, mon);
strcat(date, day);
sprintf(timeContent, "本文件最后一次打开和运行日期是%s\r\n", date);
WriteFile(hFile, timeContent, strlen(timeContent), &dwWrite, NULL);
//读取文本
DWORD fileSize = GetFileSize(hFile, NULL);
ReadFile(hFile, readBuffer, fileSize, &dwRead, NULL);
readBuffer[fileSize] = '\0';
printf("%s\n", readBuffer);
CloseHandle(hFile);
//循环将读取的命令分隔开来
char tmpBuffer[1000] = { 0 };
for (int i = 0; i<fileSize; i++)
{
if ('\r' == readBuffer[i])
{
strncpy(commandName[num], readBuffer, i);
i = i + 2;
num++;
strcpy(tmpBuffer, &readBuffer[i]);
strcpy(readBuffer, tmpBuffer);
i = 0;
}
else if ('\0' == readBuffer[i])
{
strncpy(commandName[num], readBuffer, i);
num++;
break;
}
}
for (int j = 0; j<num; j++)
create(commandName[j]);
return 0;
}
4)编写“算命大师.bat”
任务环境:Windows 10 x64
代码实现:
@Echo Off
Set /p yearmonthday=请输入: 出生年月日 (例如20000731):
Set year=%yearmonthday:~0,4%
Set monthday=%yearmonthday:~4,4%
Set /a mod=%year%%%12
if %mod%==0 set /p="你属猴,"<nul
if %mod%==1 set /p="你属鸡,"<nul
if %mod%==2 set /p="你属狗,"<nul
if %mod%==3 set /p="你属猪,"<nul
if %mod%==4 set /p="你属鼠,"<nul
if %mod%==5 set /p="你属牛,"<nul
if %mod%==6 set /p="你属虎,"<nul
if %mod%==7 set /p="你属兔,"<nul
if %mod%==8 set /p="你属龙,"<nul
if %mod%==9 set /p="你属蛇,"<nul
if %mod%==10 set /p="你属马,"<nul
if %mod%==11 set /p="你属羊,"<nul
if "%monthday%" LEQ "0119" echo 魔蝎座
if "%monthday%" GEQ "0120" if "%monthday%" LEQ "0218" echo 水瓶座
if "%monthday%" GEQ "0219" if "%monthday%" LEQ "0320" echo 双鱼座
if "%monthday%" GEQ "0321" if "%monthday%" LEQ "0419" echo 白羊座
if "%monthday%" GEQ "0420" if "%monthday%" LEQ "0520" echo 金牛座
if "%monthday%" GEQ "0521" if "%monthday%" LEQ "0621" echo 双子座
if "%monthday%" GEQ "0622" if "%monthday%" LEQ "0722" echo 巨蟹座
if "%monthday%" GEQ "0723" if "%monthday%" LEQ "0822" echo 狮子座
if "%monthday%" GEQ "0823" if "%monthday%" LEQ "0922" echo 处女座
if "%monthday%" GEQ "0923" if "%monthday%" LEQ "1023" echo 天秤座
if "%monthday%" GEQ "1024" if "%monthday%" LEQ "1122" echo 天蝎座
if "%monthday%" GEQ "0321" if "%monthday%" LEQ "0419" echo 白羊座
if "%monthday%" GEQ "1222" echo 魔蝎座
%0 :: 用于循环
Pause
补充说明:最好加入一定的容错机制,比如输入的字符串长度有误/日期不存在等等。
四、实验结果
1)编译并启用新Linux内核
Ubuntu高级选项中出现了新的内核,进入新内核后,Linux内核版本由原先的4.5.0-29-generic变为4.11.9,新Linux内核编译并启用成功
2)为Linux内核增加新的系统调用
3)实现进程创建、文件读写
①D:\OSCourse目录下有1.exe、2.exe、3.exe三个可执行程序,CommandList.txt内容如图所示:
②运行程序,1.exe、2.exe、3.exe进程均被创建
③任务管理器截图:
④CommandList.txt内容变为:
4)编写“算命大师.bat”
①输入8位年月日,自动计算出属相和星座
②继续输入,可以反复计算
五、体会
通过本次实验,我对操作系统生成的概念和过程、操作系统的操作界面与系统调用有了更深刻的理解,掌握了Linux内核的编译、系统调用的增加与Windows批处理程序的编写,对操作系统的功能与原理有了进一步的了解。
还没有评论,来说两句吧...