《操作系统原理》实验一:编译新内核并为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批处理程序的编写,对操作系统的功能与原理有了进一步的了解。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值