北大操作系统实验(二)系统调用

发布时间:2019-09-16  栏目:LINUX  评论:0 Comments

一、实验目标

(一)理解应用程序怎么着调用系统调用

在常常状态下,调用系统调用和调用三个常备的自定义函数在代码上并不曾什么样界别,但调用后发出的作业有非常大不一致。调用自定义函数是通过call指令直接跳转到该函数的地址,继续运营。而调用系统调用,是调用系统库中为该系统调用编写的四个接口函数,叫API(Application
Programming
Interface)(它对应三个宏_syscallx,在unistd.h中)。API并不可能达成系统调用的真正功效,它要做的是去调用真正的类别调用,进程是:

  • 把系统调用的数码存入EAX
  • 把函数参数存入别的通用贮存器
  • 触发0x80号中断(int 0x80)
  • 接下去就是内核的暂停管理了,自动调用函数system_call(在kernel/system_call.s中),到sys_call_table找到系统调用号对用的体系调用sys_xxx,执行它。
  1. 翻阅文本lib/close.c、fs/open.c、kernel/system_call.s、include/unistd.h、include/linux/sys.h,寻找类别调用close与那些文件之间的涉嫌,清晰close系统调用的长河;

  2. 参照他事他说加以考察种类调用close,在地方一各样文件中增进或修改系统调用iam和whoami相关的内容(系统调用号、系统调用表、系统调用总量等);

  3. 创设who.c文件,在里面分别编写制定包括具体落到实处细节的sys_iam()和sys_whoami()函数;

  4. 修改Makefile,以便在推行make命令时能够编写翻译who.c文件;

  5. 编译linux内核,运行bochs;

  6. 编辑测量检验程序iam.c和whoiam.c;

这次实验必要修改unistd.h sys.h system_call.s makefile,并编写who.c
iam.c whoami.c

1、领会操作系统的系统功效调用。

(1)修改linux-0.11/include/linux/sys.h

依照Linux调用系统调用的长河,必要把
iam()与whoami()五个函数加到全局变量,和间断函数表中就足以了,中断被调用的时候,先找找中断向量表,找到呼应的函数名,调用其函数。

分别增加表明到最下边和数组中

extern int sys_setup();
extern int sys_exit();
extern int sys_fork();
extern int sys_read();
extern int sys_write();
extern int sys_open();
extern int sys_close();
extern int sys_waitpid();
extern int sys_creat();
extern int sys_link();
extern int sys_unlink();
extern int sys_execve();
extern int sys_chdir();
extern int sys_time();
extern int sys_mknod();
extern int sys_chmod();
extern int sys_chown();
extern int sys_break();
extern int sys_stat();
extern int sys_lseek();
extern int sys_getpid();
extern int sys_mount();
extern int sys_umount();
extern int sys_setuid();
extern int sys_getuid();
extern int sys_stime();
extern int sys_ptrace();
extern int sys_alarm();
extern int sys_fstat();
extern int sys_pause();
extern int sys_utime();
extern int sys_stty();
extern int sys_gtty();
extern int sys_access();
extern int sys_nice();
extern int sys_ftime();
extern int sys_sync();
extern int sys_kill();
extern int sys_rename();
extern int sys_mkdir();
extern int sys_rmdir();
extern int sys_dup();
extern int sys_pipe();
extern int sys_times();
extern int sys_prof();
extern int sys_brk();
extern int sys_setgid();
extern int sys_getgid();
extern int sys_signal();
extern int sys_geteuid();
extern int sys_getegid();
extern int sys_acct();
extern int sys_phys();
extern int sys_lock();
extern int sys_ioctl();
extern int sys_fcntl();
extern int sys_mpx();
extern int sys_setpgid();
extern int sys_ulimit();
extern int sys_uname();
extern int sys_umask();
extern int sys_chroot();
extern int sys_ustat();
extern int sys_dup2();
extern int sys_getppid();
extern int sys_getpgrp();
extern int sys_setsid();
extern int sys_sigaction();
extern int sys_sgetmask();
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 };//记得在中断向量表的最后填上系统调用

2、通晓用C语言完毕系统机能调用的法子和步骤。

(2) 修改系统调用数:

system_call.s 在 linux-0.11/kernel 中
需要把nr_system_calls 由72改为 74 表示了暂停函数的个数。

sa_handler = 0
sa_mask = 4
sa_flags = 8
sa_restorer = 12

nr_system_calls = 74

(3)新添系统调用 号:
unistd.h 不能够一向在oslab间接直接改动,
而急需在设想机中期维修改,
在oslab中有一个mount-hdc脚本
运作sudo ./mount-hdc 能够把设想机硬盘挂载在oslab/hdc 目录下。
(那些也足以兑现文件分享)
在hdc/usr/include 目录下修改unistd.h
卡在那二日的行经.

#define __NR_setup    0   /* used only by init, to get system going */
#define __NR_exit    1
#define __NR_fork    2
#define __NR_read    3
#define __NR_write    4
#define __NR_open    5
#define __NR_close    6
#define __NR_waitpid    7
#define __NR_creat    8
#define __NR_link    9
#define __NR_unlink    10
#define __NR_execve    11
#define __NR_chdir    12
#define __NR_time    13
#define __NR_mknod    14
#define __NR_chmod    15
#define __NR_chown    16
#define __NR_break    17
#define __NR_stat    18
#define __NR_lseek    19
#define __NR_getpid    20
#define __NR_mount    21
#define __NR_umount    22
#define __NR_setuid    23
#define __NR_getuid    24
#define __NR_stime    25
#define __NR_ptrace    26
#define __NR_alarm    27
#define __NR_fstat    28
#define __NR_pause    29
#define __NR_utime    30
#define __NR_stty    31
#define __NR_gtty    32
#define __NR_access    33
#define __NR_nice    34
#define __NR_ftime    35
#define __NR_sync    36
#define __NR_kill    37
#define __NR_rename    38
#define __NR_mkdir    39
#define __NR_rmdir    40
#define __NR_dup    41
#define __NR_pipe    42
#define __NR_times    43
#define __NR_prof    44
#define __NR_brk    45
#define __NR_setgid    46
#define __NR_getgid    47
#define __NR_signal    48
#define __NR_geteuid    49
#define __NR_getegid    50
#define __NR_acct    51
#define __NR_phys    52
#define __NR_lock    53
#define __NR_ioctl    54
#define __NR_fcntl    55
#define __NR_mpx    56
#define __NR_setpgid    57
#define __NR_ulimit    58
#define __NR_uname    59
#define __NR_umask    60
#define __NR_chroot    61
#define __NR_ustat    62
#define __NR_dup2    63
#define __NR_getppid    64
#define __NR_getpgrp    65
#define __NR_setsid    66
#define __NR_sigaction    67
#define __NR_sgetmask    68
#define __NR_ssetmask    69
#define __NR_setreuid    70
#define __NR_setregid    71   /*Linux system_call total 72*/
#define __NR_iam    72     /*new system_call 72 and 73*/
#define __NR_whoami    73

3、领会运用10H号功能调用(BIOS的显示I/O成效调用)来兑现对荧屏的操作与垄断。

(4)新增添who.c文件,实现系统调用的函数:

将实现的who.c文件放入linux-0.01/kernel 目录下

#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 文件

让我们加多的kernel/who.c能够和其它Linux代码编写翻译链接到一同,需要求修改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插手到基本中了

make all 
编译系统

(6) 新扩充iam.c 跟whoami.c文件以测量检验是不是丰硕系统调用成功:
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;
}

注:那多个C文件是亟需在 你改改过的linux 0.11本子上编译的,假如嫌在 0.11
里边用vi 写代码太烦,能够在虚构机中写好, 在oslab中运作

sudo ./mount-hdc 

能够把虚构机硬盘挂载在oslab/hdc 目录下。
然后再将文件复制到 oslab/hdc/user/root/下
/user/root/ 便是您的linux 0.11 开机后所在目录
好了, 写完了,运行run

cd /home/fgx/oslab
./run

运作系统
(7)编译 iam.c 跟 whoami.c

gcc -o iam iam.c 
gcc -o whoami whoami.c 

运维一波,欢娱来啊~

图片 1

image.png

1、在显示屏的钦点区域内呈现字符串。(必做题)

2、在显示屏的制定区域内画框,在框内显示字符串。(进步题)

3、在显示屏上钦点区域内画框并以动画情势显得字符串。(选做题)

清屏子程序:

void cls(void)

{ union REGS r;

  r.h.ah=6; /*子功效号*/

  r.h.al=0;   

r.h.ch=0; /*左上角坐标*/

  r.h.cl=0;

  r.h.dh=24; /*右下角坐标*/

  r.h.dl=79;

  r.h.bh=7; /*7意味黑色*/

  int86(0x10,&r,&r); /*系统功用调用*/

 }

定位子程序:

void locate(int x, int y)

{ union REGS r;

  r.h.ah=2; /*子作用号*/

  r.h.dh=x; /*定位点坐标*/

r.h.dl=y;

r.h.bh=0;

int86(0x10,&r,&r);

}

在钦点地方写参数:

void writech(int x , int y, char ch ,int attr)

{ union REGS r;

  locate(x ,y);

  r.h.ah=9;

  r.h.bh=0;

  r.h.al=ch;

r.h.bl=attr

r.x.cx=1;

int86(0x10,&r,&r);

}

荧屏画框能够用制表符来画。其注重措施是一再调用writech函数,在钦定区域周边展现制表符,进而勾勒出一个窗口的概略。

制表符   ASCII码

┛ 217

┏ 218

┓ 191

┗ 192

┃ 179

━ 196

留下评论

网站地图xml地图