首页 > 其他分享 >Lab2:System Call

Lab2:System Call

时间:2024-03-28 18:24:27浏览次数:48  
标签:调用 struct trace mask System Lab2 Call call proc

trace

该系统调用程序,可以跟踪其他的系统调用命令,该系统调用的形参为一个整数掩码。其具体实参为1 << sys_call所得到的整数值,sys_call是一个系统调用指令在内核中定义的系统调用编号。返回值包含进程id,系统调用sys_call的名称和返回值。并且trace指令可以跟踪当前进程和它派生的所有子进程。
即具体用法为

trace [sys_call_mask] [call] [call_params]

call: 可以为一个unix命令 如grep
sys_call_mask: 为系统调用指令,可以传入2147483647,可以跟踪运行call指令期间的所有系统调用指令
call_params:即call命令需要的合法参数格式

trace.c

trace
可以看到,在该自定义函数中调用了trace的sys_call,如果成功那么将进行切割,nargv为sys_call_mask后的具体指令,然后利用exec系统调用进行执行

添加原型、存根、系统调用编号

提示中说到需要在usys.h添加系统调用的原型

可以看到原本xv6中系统调用指令的原型
trace指令通过接受整型mask返回一个字符串

char* trace(int);

第二步在usys.pl中添加存根,Makefile将调用该perl脚本,生成实际的系统调用存根usys.S

entry("trace");

第三步在syscall.h中添加系统调用编号

#define SYS_trace 22

内核中的实现

上述步骤只实现了trace指令的声明,还需要在内核中进行实现。
第一步需要在proc.h中的proc结构体内定义一个新的变量,用来记录我们给定的mask值,然后和之后的每个系统调用的mask值进行比较,如果相等则打印输出

第二步就是实现sys_trace函数,该函数主要功能就是对proc结构体中的trace_mask值进行赋值操作,需要使用argint函数,当进行系统调用时,会向a0寄存器中写入当前系统调用指令的mask即系统调用指令所需要的参数会存放到a0和a1中,利用argint函数可以从a0寄存器中获取,然后将其转换为整数。
在执行某个系统调用指令时,a0和a1用来接受参数,当函数返回时a0会存放返回值

//sys_trace()
uint64
sys_trace(void)
{
	//get the param of the sys_call
	if(argint(0,&(myproc()->trace_mask))<0)
	{
		return -1;
	}
	return 0;
}

打印子进程

由于要求打印父进程会派生出的所有子进程,所以需要将父进程的trace_mask传入到子进程里面,可以在fork()函数中实现,fork函数中会创建两个proc的结构体一个代表子进程np,一个代表当前进程p

np->trace_mask = p->trace_mask;

打印输出

调用trace指令后,我们需要对满足输入mask的系统调用进行输出
p->trapframe->a7表示当前系统调用的号码。我们可以通过比较(1<<(p->trapframe->a7))和存放在proc中的之前a0寄存器中的值来进行判断

if((1<<num) & p->trace_mask)
{
	    printf("%d: syscall %s -> %d\n", p->pid,syscalls_name[num],p->trapframe->a0);
}

输出格式按照样例格式,syscalls_name[]为新建的数组,用来存储每个系统调用的名称。

sysinfo

该系统调用主要作用是收集正在运行的系统信息,形参为定义在kernal/sysinfo.h文件下的sysinfo结构体指针,在内核态填写这个结构体,然后返回到用户空间

获取空闲内存空间

根据提示,在kalloc.c中添加函数,kalloc.c中有两个结构体,分别表示当前内存空间和空闲的内存空间

struct run {
  struct run *next;
};

struct {
  struct spinlock lock;
  struct run *freelist;
} kmem;

所以我们获得空间内存空间大小就是获得freelist这个链表的长度,直接遍历计数即可

void
getfree(uint64 *res)
{
	*res = 0;
	struct run *cur = kmem.freelist;
	//lock
	acquire(&kmem.lock);
	while(cur)
	{
		//Base: PGSIZE
		*res += PGSIZE;
		cur = cur->next;
	}
	release(&kmem.lock);
}

获取当前的进程数量

proc.c中定义了一个存储所有进程结构体的数组,我们只需要统计其中state!=UNUSED的进程即可

void
getprocnum(uint64* num)
{
	*num = 0;
	struct proc* p;
	for(p = proc; p < &proc[NPROC]; p++)
	{
		acquire(&pid_lock);
		if(p->state != UNUSED) (*num)++;
  		release(&pid_lock);
	}
}

通过系统调用复制到用户空间

编写sys_sysinfo系统调用指令,提示中也说到使用copyout()指令,首先我们需要定义一个sysinfo的结构体,然后通过上述两个函数对两个值进行赋值操作。
然后我们需要得到用户空间下的地址,可以利用argaddr函数从a0寄存器中获取然后赋值给我们的变量。当得到用户空间的地址后,利用copyout函数进行从内核到用户空间的复制操作。p->pagetable所代表的就是当前进程的页表,然后addr就是该页表下的地址。

uint64
sys_sysinfo(void)
{
	//the struct of sysinfo
	struct sysinfo info;
	getfree(&info.freemem);
	getprocnum(&info.nproc);
	struct proc* p = myproc();
	//the kernal memory addr use argaddr
	uint64 addr;
	if(argaddr(0,&addr) < 0)
	{
		return -1;
	}
	if(copyout(p->pagetable, addr, (char*)&info, sizeof(info)) < 0)
	{
		return -1;
	}
      	return 0;
}

注意

  1. 由于在sysproc.c中使用了struct sysinfo,所以需要在头文件添加sysinfo.h
  2. 需要在defs.h中对我们定义在kalloc.c和proc.c的两个函数进行声明
    defs.h定义了整个操作系统中会用到的结构体,枚举类型和函数

声明一个系统调用

定义一个系统调用

标签:调用,struct,trace,mask,System,Lab2,Call,call,proc
From: https://www.cnblogs.com/XTG111/p/18101620

相关文章

  • Napi::CallbackInfo Napi::Env
    Napi::ValueEncryptPassword(constNapi::CallbackInfo&info){Napi::Envenv=info.Env();/*Napi::Envenv=info.Env();if(info.Length()<2){Napi::TypeError::New(env,"参数个数异常").ThrowAsJavaScriptExcepti......
  • SystemServer 启动流程
    SystemServer启动流程一、介绍SystemServer是Android进入Launcher前的最后准备,顾名思义,它提供了众多由Java语言编写的服务在Zygote自启动过程中,参数boolstartSystemServer为真的话,那么在ZygoteInit.java/main()就会调用函数forkSystemServer()生成SystemSer......
  • js 回调 callback
    <html><head><title>按钮点击事件示例</title><script>functiona(callback){console.log("执行函数a!");console.log("调用回调函数");callback();//调用回调函数}functionb(){console.log("回调函数b"......
  • this指向&call,apply,bind的用法及手写
    我们知道call,apply,bind主要用来修改this指向。那么这三个方法的用法区别是什么?具体是怎么修改this 指向的?我们该如何手写自己的call,apply,bind函数?我们先从this指向讲起。明白了this在不同情况的指向,再来看这三个方法在操纵this的具体情况及异同,明白其作用后再......
  • 【Azure Cloud Service】部署云服务时候遇见 Last exit code: 0. Last role exception
    问题描述部署云服务时候遇见Lastexitcode:0.Lastroleexception:(System.IO.FileNotFoundException)错误,提示无法加载System.Runtime。Recoveringrole...Applicationstartuptask0finishedsuccessfully.Lastexittime:[2024/03/27,20:23:31.142].Lastexit......
  • System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3
    VS2022.netCore5.0项目编译没问题,运行时报这个错System.IO.FileNotFoundException:“Couldnotloadfileorassembly'System.Runtime,Version=6.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a'.系统找不到指定的文件。” 我这里遇到这个问题的原因是,v......
  • Android Framework system_server进程启动
    哈喽大家我是Zzz.今天分享的blog是system_server进程的启动,环境基于aosp13_r6,话不多说直接上干货前言:system_server是系统核心服务的一个进程,这个进程包含了系统中核心Service的运行,给系统提供如:Window的管理、Activity的管理,系统的核心功能都在System_server中;在ZygoteIni......
  • BitLocker和EFS(Encrypting File System)是Windows操作系统中用于数据加密的两种不同的
    BitLocker和EFS(EncryptingFileSystem)是Windows操作系统中用于数据加密的两种不同的功能。BitLocker:BitLocker是一种全磁盘加密技术,它可以加密整个硬盘驱动器上的数据,包括操作系统、应用程序和用户数据等。BitLocker可以保护计算机在启动时的数据安全,并且可以通过预启动认......
  • Building an Automatically Scaling Web Application
    2024年春季云计算课业1:构建一个自动伸缩的Web应用程序截止日期:2024年4月15日,星期一1目标和范围在这项任务中,我们将为(非常)琐碎的Web构建一个小型的自动伸缩测试平台应用任务的目标是熟悉伸缩Web的各个方面应用程序,这将提高您对低级/基本实现的理解云系统的详细信息。正如我们在......
  • System.Security.Cryptography.RijndaelManaged()
    以下为ai生成:System.Security.Cryptography.RijndaelManaged 是.NET框架中的一个加密类,用于提供高级加密标准(AES)算法的实现。AES是一种强大的对称加密算法,它可以用于保护数据的安全。以下是一个使用RijndaelManaged进行数据加密和解密的简单例子:usingSystem;usingSystem.I......