操作系統實驗(2:系統調用)

實驗目的

1.建立對操作系統接口的深入認識
2.掌握系統調用的基本過程
3.能完成系統調用的全面控制

實驗內容

在Linux 0.11上添加兩個系統調用,並編寫兩個簡單的應用程序測試該系統調用。實驗過程分兩步。

第一步是在Linux 0.11上增加一個系統調用whoami(),原型如下:
int whoami(void);

該系統調用的功能是將用戶的名字(例如:Li Zhijun)打印到屏幕上。用戶的名字字符串寫在內核源代碼中。然後在Linux 0.11下編寫一個測試程序whoami,它調用whoami()獲得自己的名字,並在標準輸出設備(通常就是屏幕上)打印字符串“I am XXX.”。返回值是任意非負數。

第二步在Linux 0.11上再添加一個系統調用iam(),其接口是:
int iam(const char * name);

完成的功能是將用戶程序中傳入的字符串參數name的內容拷貝到核心態數據段中。要求name的長度不能超過20個字符。可以假設在覈心態數據段中有一個全局變量:char myname[21],iam將用戶態數據name拷貝到核心態數據myname中。返回值是拷貝的字符數。如果name的字符個數超出了myname的存儲能力,則返回“-EINVAL”。

然後修改的上面的whoami(),新的原型爲:
int whoami(char* name, unsigned int size);

它不再向屏幕輸出任何內容,而是拷貝myname到name中,同時確保不會對name越界訪存(name的大小由size說明)。返回值是拷貝的字符數。如果size小於需要的空間,則返回“-EINVAL”。

然後再實現一個測試程序iam。最終要求的結果是:
$ iam lizhijun
$ whoami
$ I am lizhijun

以上截取至實驗指導書。

實驗步驟

實驗步驟參考了簡書上寒夏涼秋的文章。鏈接如下:
https://www.jianshu.com/p/5786cd42b152
(侵刪)

1.修改sys.h

進入linux-0.11/include/linux目錄,打開sys.h文件,在全局變量和中斷函數表中添加iam()和whoami()兩個函數。
在這裏插入圖片描述

2.修改system_call.s

由於新增了兩個中斷函數,所以需要修改中斷函數的個數。進入linux-0.11/kernel目錄,打開system_call.s,修改nr_system_calls爲74。
在這裏插入圖片描述

3.增加系統調用號

由於unistd.h不能直接修改,我們要把虛擬硬盤掛載在oslab/hdc目錄下,在終端輸入命令:
sudo ./mount-hdc

然後進入hdc/usr/include目錄,打開unistd.h,在系統調用的定義中增加兩行:
#define __NR_iam 72
#define __NR_whoami 73
在這裏插入圖片描述
4.實現內核函數
進入linux-0.11/kernel目錄,新建who.c,實現sys_iam()和syswhoami(),代碼如下:

#include <string.h>
#include <errno.h>
#include <asm/segment.h>

char msg[24];

int sys_iam(const char * name)
{
    char tep[26];
    int i = 0;
    for(; i < 26; i++)
    {
        tep[i] = get_fs_byte(name+i);
        if(tep[i] == '\0')  break;
    }

    if (i > 23) return -(EINVAL);

    strcpy(msg, tep);
    return i;
}

int sys_whoami(char * name, unsigned int size)
{
    int len = 0;
    for (;msg[len] != '\0'; len++);
    
    if (len > size) 
    {
        return -(EINVAL);
    }
    
    int i = 0;
    for(i = 0; i < size; i++)
    {
        put_fs_byte(msg[i], name+i);
        if(msg[i] == '\0') break;
    }
    return i;
}

5.修改Makefile文件

進入linux-0.11/kernel目錄,打開Makefile,

OBJS  = sched.o system_call.o traps.o asm.o fork.o \
        panic.o printk.o vsprintf.o sys.o exit.o \
        signal.o mktime.o

改爲:

OBJS  = sched.o system_call.o traps.o asm.o fork.o \
        panic.o printk.o vsprintf.o sys.o exit.o \
        signal.o mktime.o who.o

另外將:

### Dependencies:
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
  ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
  ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \

改爲:

### Dependencies:
who.s who.o: who.c ../include/linux/kernel.h ../include/unistd.h
exit.s exit.o: exit.c ../include/errno.h ../include/signal.h \
  ../include/sys/types.h ../include/sys/wait.h ../include/linux/sched.h \
  ../include/linux/head.h ../include/linux/fs.h ../include/linux/mm.h \

在這裏插入圖片描述
在這裏插入圖片描述
修改完後編譯所有文件生成新的image文件。

6.編寫測試文件

新建iam.c,代碼如下:

#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
_syscall1(int,iam,const char*,name)

int main(int argc,char* argv[])
{
    iam(argv[1]);
    return 0;
}

新建whoami.c,代碼如下:

#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <stdio.h>

_syscall2(int, whoami, char*, name, unsigned int, size);

int main(int argc, char ** argv)
{
    char t[30];
    whoami(t, 30);
    printf("%s\n", t);
    return 0;
}

將這兩個文件複製到hdc/usr/root目錄下。

7.運行系統

在終端上切換目錄爲oslab,輸入./run打開bochs從而運行linux,在bochs中輸入以下命令編譯iam.c和whoami.c:
gcc -o iam iam.c
gcc -o whoami whoami.c

然後輸入以下命令測試:
./iam handsomeboy
./whoami

輸出了handsomeboy,實驗完成。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章