菜单

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

2018年12月27日 - LINUX

一、实验目标

(一)精晓应用程序如何调用系统调用

在平日状态下,调用系统调用和调用一个平日的自定义函数在代码上并从未什么样界别,但调用后发生的事务有很大不同。调用自定义函数是因而call指令直接跳转到该函数的地方,继续运行。而调用系统调用,是调用系统库中为该系统调用编写的一个接口函数,叫API(Application
Programming
Interface)(它对应一个宏_syscallx,在unistd.h中)。API并不可能完成系统调用的真正效率,它要做的是去调用真正的体系调用,过程是:

  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地图