實驗目的
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,實驗完成。