xv6操作系统中增加一个系统调用

本文情景:xv6系统中,不自带Linux下的ps命令,不能直观查看各个进程的状态。为此,需要新增一个系统调用sys_cps(),通过它查看进程,将进程名,pid和优先级打印出来,为之后的调度算法实现做准备。

涉及到的文件有:

syscall.c
syscall.h
usys.S
user.h
sysproc.c
proc.c
proc.h
defs.h

准备工作

xv6中的进程是不带有优先级的,因此需要在进程结构体struct proc中加入一个表示优先级的成员。(在proc.h中)引入priority表示优先级,最终的proc如下:
在第52行进行修改

// Per-process state
struct proc {
  uint sz;                     // Size of process memory (bytes)
  pde_t* pgdir;                // Page table
  char *kstack;                // Bottom of kernel stack for this process
  enum procstate state;        // Process state
  int pid;                     // Process ID
  struct proc *parent;         // Parent process
  struct trapframe *tf;        // Trap frame for current syscall
  struct context *context;     // swtch() here to run process
  void *chan;                  // If non-zero, sleeping on chan
  int killed;                  // If non-zero, have been killed
  struct file *ofile[NOFILE];  // Open files
  struct inode *cwd;           // Current directory
  char name[16];               // Process name (debugging)
  int priority;		           // (0-20)  **新增部分**
};

proc.c修改

proc.c中有一个初始化程序,我们设置在创建一个进程的时候,可以默认将其优先级设定为10,在proc.c中的allocproc函数中,found模块下,修改p->priority=10即可。(图中倒数第二行)
第91行新增

found:
  p->state = EMBRYO;
  p->pid = nextpid++;
  p->priority = 10;  **新增部分**

开始加入系统调用

1、首先,在proc.c中,实现具体的系统调用函数功能,此时它只是一个普通的函数,还不是一个系统调用。此处,实现的函数cps()功能即为遍历进程池,打印每个进程的信息,具体实现如下:(直接加在proc.c的最后)
在末尾行新增 函数实现

int 
cps(void)
{
  struct proc *p; //定义一个结构体(进程控制块)
  sti();	// 中断
  acquire(&ptable.lock); //加锁
  cprintf("name \t pid \t state \t \t priority \n"); //罗列所有的pid
  for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)  //NPROC为64
  {
    if(p->state == SLEEPING) //睡眠
    cprintf("%s \t %d \t SLEEPING \t %d\n", p->name, p->pid, p->priority);
    else if(p->state == RUNNING) //正在执行
    cprintf("%s \t %d \t RUNNING \t %d\n", p->name, p->pid, p->priority);
    else if(p->state == RUNNABLE) //可运行队列
    cprintf("%s \t %d \t RUNNABLE \t %d\n", p->name, p->pid, p->priority);
  }
  release(&ptable.lock); //释放锁
  return 22; //返回22
}

最后,cps()的返回值为22。因为cps()最终需要变成一个系统调用,而每个系统调用函数的返回值都是int,代表系统调用号。因此需要制定它的返回编号,在后续操作中,sys_cps的系统调用号即为22。

2、在user.h和defs.h中,定义该函数。(在defs.h中,定义在//proc.c那一块下),定义的语句均为:
user.h在第26行新增

int cps(void);

defs.h在第123行新增

int             cps(void);

3、在usys.S的最后,加上:
在末尾行新增

SYSCALL(cps)

至此,完成了该函数的原型实现和用户系统调用接口。然而现在它还不是一个系统调用,需要进一步配置将其加入系统调用的范围。

4、在syscall.h的最后,加入系统调用号的定义:(注意,第一步里面的函数名字(cps)和这里的系统调用标识(SYS_cps)不要同名,之后会有函数将其关联起来)
在末尾行新增

#define SYS_cps    22

5、在syscall.c中,注册该函数:(一共有两处)
第一处:(很多extern的地方,在那一段最后加):
第106行新增

extern int sys_cps(void);

第二处:(在static int (*syscalls[])(void)的大括号中)
第130行新增

[SYS_cps]     sys_cps,

在这一步中,将系统调用标识SYS_cps和系统调用函数sys_cps关联起来了。

6、最后一步,也是最关键的,那就是如何将系统调用sys_cps和功能函数cps关联起来,也就是说,只有通过这一步,cps才能成为系统调用。

在sysproc.c中,添加对于sys_cps这个系统调用函数的具体实现:(一般而言,系统调用函数用普通功能函数作为返回。)
在末尾行新增

int
sys_cps(void) 
{
  return cps();
}

至此,系统调用sys_cps会调用函数cps,即实现了系统调用的实际功能。
新增系统调用包括两大部分,一方面,需要在内核中注册它,让系统认为它是一个系统调用(包括系统调用编号、syscalls[]中的注册等),另一方面要实现系统调用的具体功能代码,这一部分和普通函数无差别。

其中,syscall.c、syscall.h两个文件定义了该系统调用标识SYS_cps和系统调用函数sys_cps,proc.c中的cps实现了该函数的具体功能,user.h和defs.h则具体定义了功能函数cps,usys.S则实现了用户访问系统调用的接口,而最后的sysproc.c是将用户和系统调用相连的关键部分。

最后,当前的系统调用已经添加好了。
以上参考自:链接

下面还需要实现输入指令ps,执行本文所实现的系统调用,打印进程信息。

在这里举的例子是博主所做的是一个ps指令(用于实现类似于Linux系统中ps指令列出进程的功能),该指令通过系统调用cps()函数打印各个进程的名字,具体实现如下:

1、新建一个源代码,命名后缀为.c(这里命名为zrzps.c)

#include "types.h"
#include "stat.h"
#include "user.h"
 
int main(int argc, char *argv[])
{
	if(argc!=1)
	printf(1, "Usage: zrzps\n");
	else
	cps();
	exit();
}

2、修改Makefile,一共有两处
makefile 184行新增

_zrzps\

makefile 254行增加

printf.c umalloc.c zrzps.c\

3、编译源文件

make qemu

在这里插入图片描述
4、ls查看当前可编辑指令
在这里插入图片描述
5、执行zrzps 调用ps打印当前的进程信息

zrzps

在这里插入图片描述

以上部分参考:链接

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值