哈工大作業系統試驗2 系統呼叫
由於一時疏忽,導致who.c的程式碼不能通過部分測試資料,現已經改正。
今天整理了一下實驗報告
在unistd.h中可以看到現在Linux 0.11 支援3個引數的傳遞。新增引數的方法大概有3條
1.可以採用ESI,EDI,EBP,ESP這幾個暫存器傳遞引數。
2.可以採用《Linux 0.11註釋》中提到的系統呼叫門的辦法。
3.可以開闢一塊使用者態的空間,允許核心態訪問,傳遞引數時,只需傳遞此空間的首地址指標即可。
向linux 0.11新增一個系統呼叫foo()的步驟:
首先。在核心中編寫系統呼叫處理函式。
其次。在include/unistd.h中新增系統呼叫的功能號(#define __NR_foo **)
並且相應的在include/linux/sys.h中宣告新的系統呼叫處理函式以及新增系統
呼叫處理程式指標陣列表中該項的索引值。在make file中新增新系統呼叫所在
檔案的編譯、連結規則(依賴關係)。修改system_call.s中系統呼叫總數。
最後。在應用程式中提供介面,呼叫系統呼叫。
這次試驗,需要用c來寫,比上次要簡單一些。
需要改寫unistd.h sys.h system_call.s makefile 4個檔案
而且需要自己寫出 who.c iam.c whoami.c 3個檔案
sys.h在 linux-0.11/include/linux 之中,原始檔關鍵處如下
extern int sys_ssetmask(); extern int sys_setreuid(); extern int sys_setregid(); fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link, sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod, sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount, sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm, sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access, sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir, sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid, sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys, sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit, sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid, sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask, sys_setreuid,sys_setregid };
只需要把 iam與whoami兩個函式加到全域性變數,和中斷函式表中就可以了,中斷被呼叫的時候,先查詢中斷向量表,
找到相應的函式名,呼叫其函式。
system_call.s 在 linux-0.11/kernel 中extern int sys_ssetmask(); extern int sys_setreuid(); extern int sys_setregid(); extern int sys_iam(); extern int sys_whoami(); fn_ptr sys_call_table[] = { sys_setup, sys_exit, sys_fork, sys_read, sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link, sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod, sys_chown, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount, sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm, sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access, sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir, sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid, sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys, sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit, sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid, sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask, sys_setreuid,sys_setregid,sys_iam,sys_whoami };
# offsets within sigaction
sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12
nr_system_calls = 72
只需要把 nr_system_calls 改為 74 就好 ,其代表了中斷函式的個數。修改後是這樣。# offsets within sigaction
sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12
nr_system_calls = 74
Makefile 試驗指導書上講得很詳細
修改Makefile
要想讓我們新增的kernel/who.c可以和其它Linux程式碼編譯連結到一起,必須要修改Makefile檔案。Makefile裡記錄的是所有源程式檔案的編譯、連結規則,《註釋》3.6節有簡略介紹。我們之所以簡單地執行make就可以編譯整個程式碼樹,是因為make完全按照Makefile裡的指示工作。
Makefile在程式碼樹中有很多,分別負責不同模組的編譯工作。我們要修改的是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 \ ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \ ../include/asm/segment.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 \ ../include/linux/kernel.h ../include/linux/tty.h ../include/termios.h \ ../include/asm/segment.h
Makefile修改後,和往常一樣“make all”就能自動把who.c加入到核心中了。如果編譯時提示who.c有錯誤,就說明修改生效了。所以,有意或無意地製造一兩個錯誤也不完全是壞事,至少能證明Makefile是對的。
unistd.h 不能直接在oslab直接直接修改,而需要在虛擬機器中修改,在oslab中有一個mount-hdc指令碼
執行sudo ./mount-hdc 可以把虛擬機器硬碟掛載在oslab/hdc 目錄下。
在hdc/usr/include 目錄下修改unistd.h
關鍵原始碼為
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
只需要把兩個自定義函式的巨集定義在這裡就好。修改後為
#define __NR_ssetmask 69
#define __NR_setreuid 70
#define __NR_setregid 71
#define __NR_iam 72
#define __NR_whoami 73
這樣修改工作就完成了成了
who.c 的程式碼如下
#define __LIBRARY__
#include <unistd.h>
#include <errno.h>
#include <asm/segment.h>
char temp[64]={0};
int sys_iam(const char* name)
{
int i=0;
while(get_fs_byte(name+i)!='\0')
i++;
if(i>23){
return -EINVAL;
}
printk("%d\n",i);
i=0;
while((temp[i]=get_fs_byte(name+i))!='\0'){
i++;
}
return i;
}
int sys_whoami(char* name,unsigned int size)
{
int i=0;
while (temp[i]!='\0')
i++;
if (size<i)
return -1;
i=0;
while(temp[i]!='\0'){
put_fs_byte(temp[i],(name+i));
i++;
}
return i;
}
寫完後吧 who.c 放到linux-0.01/kernel 目錄下 執行make all who.c 就會被編譯到核心裡了
iam.c 與 whoami.c 兩個檔案是測試用的,可以在本地寫好,通過掛載的hdc傳到linux下,也可以通過vi在linux下寫好(如果你蛋疼的話)
一定要在linux 執行編譯 ,然後執行sync確保緩衝區資料寫入磁碟就可以了。
程式碼如下
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[])
{
if(argc>1){
if(iam(argv[1])<0){
printf("SystemCall Exception!\n");
return -1;
}
}
else{
printf("Input Exception!\n");
return -1;
}
return 0;
}
whoami.c
#define __LIBRARY__
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
_syscall2(int,whoami,char*,name,unsigned int,size)
int main()
{
int counter;
char buff[128]={0};
counter=whoami(buff,128);
if(counter < 0)
{
printf("SystemCall Exception!");
return -1;
}
else{
printf("%s\n",buff);
}
return 0;
}
最後需要用指令碼測試一下,程式的正確性,把指令碼放到iam.c whoami.c同目錄下 執行就好
指令碼程式碼如下
經過分析它不會檢查你的的 erron是不是正確,只會檢查whoami返回的的字串正不正確。
最後一個數據很陰險,注意字串過長的時候,不要覆蓋之前儲存的字串,就是說所儲存的字串是之前存的字串就好。
#/bin/sh
string1="Sunner"
string2="Richard Stallman"
string3="This is a very very long string!"
score1=10
score2=10
score3=10
expected1="Sunner"
expected2="Richard Stallman"
expected3="Richard Stallman"
echo Testing string:$string1
./iam "$string1"
result=`./whoami`
if [ "$result" = "$expected1" ]; then
echo PASS.
else
score1=0
echo FAILED.
fi
score=$score1
echo Testing string:$string2
./iam "$string2"
result=`./whoami`
if [ "$result" = "$expected2" ]; then
echo PASS.
else
score2=0
echo FAILED.
fi
score=$score+$score2
echo Testing string:$string3
./iam "$string3"
result=`./whoami`
if [ "$result" = "$expected3" ]; then
echo PASS.
else
score3=0
echo FAILED.
fi
score=$score+$score3
let "totalscore=$score"
echo Score: $score = $totalscore%
另外一個測試程式testlab2.c會檢查你的返回值是否正確。
相關推薦
哈工大作業系統試驗2 系統呼叫
由於一時疏忽,導致who.c的程式碼不能通過部分測試資料,現已經改正。 今天整理了一下實驗報告 在unistd.h中可以看到現在Linux 0.11 支援3個引數的傳遞。新增引數的方法大概有3條 1.可以採用ESI,EDI,EBP,ESP這幾
作業系統實驗——增加系統呼叫(詳細圖文解釋)
Linux新增系統呼叫 注意:請提前安裝好Vmware,並準備好Ubuntu映象檔案以及Linux核心(我用的是Ubuntu10.0.4版本,核心版本是Linux-2.6.32.65.xz) 操作步驟: 1.點選建立一個新的虛擬機器 1)選擇自定義,點選下一步,接下來選擇預設配置,進入虛擬機器嚮導 2
作業系統基礎之系統呼叫
1.使用者態和核心態 使用者程式是如何呼叫核心程式的呢?考慮實現下面的一個whoami的系統呼叫: 在核心中100地址處有一個使用者“lizhijun”,whoami函式的功能是要打印出這個使用者名稱,那可以直接打印出100地址處的內容嗎?答案當然是否定
作業系統實驗之系統呼叫
1。今天整理了一下實驗報告 在unistd.h中可以看到現在Linux 0.11 支援3個引數的傳遞。新增引數的方法大概有3條 1.可以採用ESI,EDI,EBP,ESP這幾個暫存器傳遞引數。 2.可以採用《Lin
系統調用 -- 哈工大李治軍操作系統實驗2
.net pre ron 例如 中修改 TP segment val 命令 實驗環境是 實驗樓的 地址https://www.shiyanlou.com/courses/115 參考博客:https://blog.csdn.net/wangyi_lin/arti
作業系統實驗一:linux核心編譯及新增系統呼叫
編譯環境 VMWare Ubuntu Desktop Ubuntu 18.04.1映象下載地址:點我下載 裝ubuntu很簡單,網上教程一大堆,記憶體分配多點。 新增系統呼叫步驟 解壓linux核心 想辦法,把上面的linux核心弄到ubuntu裡面,可
作業系統課程設計(一):linux核心編譯及新增系統呼叫
1.實驗目的 通過實驗,熟悉Linux作業系統的使用,掌握構建與啟動Linux核心的方法;掌握使用者程式如何利用系統呼叫與作業系統核心實現通訊的方法,加深對系統呼叫機制的理解;進一步掌握如何向作業系統核心增加新的系統呼叫的方法,以擴充套件作業系統的功能。 2.實
哈工大LTP:Windows系統Python本地呼叫
本文實驗環境為64位win10系統,python3.6.2,LTP專案檔案和模型檔案使用的3.3.1版本 1.LTP下載 (1)LTP專案檔案ltp-3.3.1-win-x86.zip(下載連結) (2)LTP模型檔案3.3.1(下載連結) Windows系統直接下載
android4.2系統,實現應用層呼叫乙太網/3G網絡卡
android開發的SDK中,沒有提供3G網絡卡和乙太網的操作方法,但是有些裝置(包括平板和手機)可以在設定中開啟“乙太網”功能,就可以利用usb介面轉網線,或者3G網絡卡連線上網。也就是說系統中提供了Ethern
現代作業系統學習筆記——核心態與使用者態、系統呼叫
本文為學習《現代作業系統》時遇到的疑問,為網上查詢資料的總和。核心態與使用者態作業系統需要CPU的兩種狀態,即核心態與使用者態,兩種狀態的不同主要體現在所能使用的指令範圍上。核心態:可以執行任何指令,對所有硬體具有完全訪問權,作業系統就執行在核心態。使用者態:只能使用計算機指
Linux open系統呼叫流程(2)
1. 書結上文,繼續分析do_filp_open函式,其傳入4個引數: dfd:相對目錄 tmp:檔案路徑名,例如要開啟/usr/src/kernels/linux-2.6.30 flags:開啟標誌 mode:開啟模式 /* * Note that while the
Linux編譯核心(4.2.6)並新增系統呼叫
1. 檢視系統核心版本(ubuntu 12.04) uname –a 或者 cat /proc/version 將壓縮包linux-4.2.6.tar.gz 放至 /usr/src中後解壓: sudo cp linux-4.2.6.tar.gz /usr/src
作業系統實驗一(核心編譯,系統呼叫)
作業系統實驗一 ——-系統呼叫 注: 實驗前的準備工作就不一一敘述了。 Ubuntu執行環境:mac osx10.9.1 +VMware Fusion 6.0.2 Ubuntu 版本: 12.10 64位 具體實驗流程如下: 1.安裝有關編譯程式。(這是第二次重
Linux核心2.6.34.14新增系統呼叫及編譯方法(CentOS-6.4-x86_64)
<?xml version="1.0" encoding="UTF-8"?> //我新增系統呼叫步驟,僅供參考,尤其是系統呼叫的實現部分,建議大家自己寫,除了我這種好像還可以用sys_open系列來寫 #define 核心版本 linux-2.6.34.14
作業系統中最基本的概念——庫呼叫和系統呼叫
Unix作業系統設計上的陳述: 理解庫函式的區別和系統呼叫,首先要裡理解Unix的kernel mode和user mode。考慮下面的函式段: int main() { int fd = create("filename",0666); exit(0);
作業系統作業:給linux系統增加一個系統呼叫
前不久開了一門《作業系統》,老師上課留下了一個作業——給Linux系統新增一個系統呼叫。剛開始只能用一臉懵逼來形容,只能硬著頭皮做下去。由於剛的新電腦,所以就沒敢裝雙系統。所以我選擇了虛擬機器,虛擬機器剛開始配置的過程不算特別複雜,網上也有很多教程,於是我看著虛擬機器也是一臉懵逼,不知道從何下手,百度得知快捷
《Linux作業系統分析》之使用庫函式API和C程式碼中嵌入彙編程式碼兩種方式使用同一個系統呼叫
本篇文章分析的是使用庫函式API和C程式碼中嵌入彙編程式碼兩種方式使用同一個系統呼叫,來說明在Linux系統中,系統呼叫的實現機制。 相關知識 首先關於這篇文章會介紹一些用到的知識。 一、什麼是核心態,什麼又是使用者態。 核心態:在高執行級別下,程式碼可以執行特權指令,
《Linux作業系統分析》之分析系統呼叫system_call的處理過程
本篇文章通過將上篇文章中使用庫函式API和C程式碼中嵌入彙編程式碼兩種方式設計的系統呼叫新增到系統menu中,來說明在Linux系統中,系統呼叫的實現的時機以及具體執行,以及一般的中斷處理過程。 相關知識 首先關於這篇文章會介紹一些用到的知識。 一、將系統呼叫號與相應的服務
Windows核心情景分析-系統呼叫2
x86後來加入的快速系統呼叫硬體支援,windows則也跟著做了改動,此時如果cpu支援sysenter,則會採用快速系統呼叫的系統呼叫形式。 快速系統呼叫 sysenter 形式的系統呼叫例項 此時工具生成的NtReadFile為: 此時與int 0
我是如何學習寫一個作業系統(四):作業系統之系統呼叫
前言 最近有點事情,馬上要開學了,所以學習的腳步就慢下來了。這一篇主要是來說作業系統的系統呼叫的,像C語言的printf深入到內部就是一個有關螢幕輸出的系統呼叫 什麼是系統呼叫 之前提過作業系統是對硬體的抽象,也是軟硬體之間的一層。之前比如如果我們想要在螢幕上輸出一些字元,就需要一些指令操作,然後把資料放到視