✨ Noticias - 20/12/2024 | Ahora se publicará también contenido en inglés. Ah, ¡felices fiestas a todos! 🎉✨          🌍          ✨ News - 15/12/2024 | Now, English content will also be posted, check it at the English section. Oh, Merry Christmas everyone! 🎉✨

domingo, 15 de diciembre de 2024

'ps' system call implementation in xv6 operating system | Operating Systems - Sevilla's University

Under the pretext of a school volunteer project, I chose to dig into xv6 OS to understand how processes work in a given operating system. First, I had to download every tool needed to launch xv6 from Windows 10's command line. I also had to download xv6 itself.

Modifications on xv6

Quick start: hello and shutdown system calls

In the root directory where xv6 is located, there are so many files that could confuse the untrained eye. Other xv6 repositories seem better organized than this one out there just so you know, it is a matter of making a couple of searches.

I initially chose to write a small and basic system call named hello which would just print any message in the terminal (some sort of Hello World). To implement the system call shutdown, a system call called halt will also be included. 

A few modifications were needed in the files syscall.c, syscall.h, user.h, usys.ssysproc.c, and Makefile besides new files called hello.c, shutdown.c, and halt.c.

Modifications in syscall.h

// System call numbers
#define SYS_fork    1
#define SYS_exit    2
// (...)
#define SYS_close  21
#define SYS_halt   22 // Added
#define SYS_hello  23 // Added

Modifications in syscall.c

extern int sys_chdir(void);
extern int sys_close(void);
extern int sys_dup(void);
// (...)
extern int sys_uptime(void);
extern int sys_halt(void); // Added
extern int sys_hello(void); // Added
static int (*syscalls[])(void) = {
[SYS_fork]    sys_fork,
[SYS_exit]    sys_exit,
// (...)
[SYS_close]   sys_close,
[SYS_halt]    sys_halt, // Added
[SYS_hello]   sys_hello // Added
};

Modifications in usys.s

SYSCALL(fork)
SYSCALL(exit)
SYSCALL(wait)
// (...)
SYSCALL(uptime)
SYSCALL(halt) // Added
SYSCALL(hello) // Added

Modifications in user.h

// system calls
int fork(void);
int exit(void) __attribute__((noreturn));
// (...)
int uptime(void);
int halt(void); // Added
int hello(void); // Added

Modifications in sysproc.c

// (...)
int
sys_hello(void)
{
 cprintf("### Hello World ###\n");
 return 0;
}
int
sys_halt(void)
{
  outb(0xf4, 0x00);
  return 0;
}

Modifications in Makefile

# (...)
UPROGS=\
 _cat\
 _echo\
# (...)
 _shutdown\ # Added
 _hello\ # Added
# (...)
QEMUOPTS = -drive file=fs.img,index=1,media=disk,format(...) 
-device isa-debug-exit,iobase=0xf4,iosize=0x04 # Added
# (...)
EXTRA=\
# (...)
 shutdown.c\ # Added
 hello.c\ # Added
 printf.c umalloc.c\
# (...)

Content of hello.c

#include "types.h"
#include "user.h"
int main(void)
{
        hello();
        
        /*
        * Unlike another OS, in xv6 it is needed to call exit() so resources can be freed.
        * Otherwise, this will not finish its execution correctly and error messages will rise.
        */
        exit();
}

Content of halt.c

int
sys_halt(void)
{
  outb(0xf4, 0x00);
  return 0;
}

Content of shutdown.c

#include "types.h"
#include "user.h"
int main(void){
 halt();
 exit();
}

With these changes, it is now possible to launch both the hello and shutdown system calls. The hello system call simply prints a message in the command line. The shutdown system call shuts the system down.

All the information I needed to implement the shutdown system call: "Adding New System Calls to xv6."

Checking processes status using the ps system call

To implement the process status system call I had to retrieve the code from andear@github, which reorganizes the xv6 project in a much more comprehensive way using modules.

Changes in the files syscall.h, syscall.c, user.h, usys.s, sysproc.c, sysfunc.h, makefile.mk, proc.c, and defs.h were needed. Also, two new files ProcessInfo.h and ps.c were created.

Modifications in syscall.h

// (...)
#define SYS_getprocs number

Modifications in syscall.c

// (...)
[SYS_getprocs] sys_getprocs

Modifications in user.h

// system calls
int fork(void);
int exit(void) __attribute__((noreturn));
// (...)
int getprocs(struct ProcessInfo* processInfoTable); // Added
int halt(void);
int hello(void);

Modifications in usys.s

SYSCALL(fork)
SYSCALL(exit)
// (...)
SYSCALL(getprocs) // Added
SYSCALL(halt)
SYSCALL(hello)

Modifications in sysproc.c

#include "ProcessInfo.h" *
// (...)
int 
sys_getprocs(void){
  struct ProcessInfo *processInfoTable;
  if(argptr(0,(char**)&processInfoTable,sizeof(struct ProcessInfo) * NPROC) < 0) {
    return -1;
  }
  return getprocs(processInfoTable);

}

Modifications in sysfunc.h

// System call handlers
int sys_chdir(void);
int sys_close(void);
// (...)
int sys_getprocs(void); // Added
int sys_hello(void);
int sys_halt(void);

Modifications in makefile.mk

USER_PROGS := \
 cat\
 echo\
# (...)
 ps\ # Added
 shutdown\
 hello\

Modifications in proc.c

#include "ProcessInfo.h" *
// (...)
int 
getprocs(struct ProcessInfo* processInfoTable){
  struct proc *p;  
  int count = 0;
  int i;
  for (i = 0, p = ptable.proc; p < &ptable.proc[NPROC] && i < NPROC; i++,p++)
  {
    if(p->state == UNUSED)
    {
      continue;
    }
    count++;
    processInfoTable[i].pid = p->pid;
    if(i == 0){
        processInfoTable[i].ppid = 0;
    }
    else{
         processInfoTable[i].ppid = p->parent->pid;
    }
   
    processInfoTable[i].state = p->state;
    processInfoTable[i].sz = p->sz;
    for (int j = 0; j < 16; j++)
    {
       processInfoTable[i].name[j] = p->name[j];
    }
  }
  p = NULL;
  return count;
}

Modifications in defs.h

// proc.c
// (...)
void yield(void);
int getprocs(struct ProcessInfo*); // Added

Content of ProcessInfo.h

#ifndef _PROCESSINFO_H_
#define _PROCESSINFO_H_
#include "types.h"
struct ProcessInfo{
 int pid;
 int ppid;
 int state;
 uint sz;
 char name[16];
};
#endif

Content of ps.c

#include "ProcessInfo.h"
#include "types.h"
#include "stat.h"
#include "user.h"
#include "param.h"
int main(void)
{
 enum procstate { UNUSED, EMBRYO, BLOCKED, READY, ACTIVE, ZOMBIE };
  static char *states[] = {
    [UNUSED]    "UNUSED  ",
    [EMBRYO]    "EMBRYO  ",
    [BLOCKED]  "BLOCKED",
    [READY]  "READY",
    [ACTIVE]     "ACTIVE   ",
    [ZOMBIE]     "ZOMBIE   "
    };
  
 printf(1, "\n  PID\sSTATUS\t\tMEM\tPROC\n");
 printf(1,"\n");
   
 struct ProcessInfo processInfoTable[NPROC];
 int numbers = getprocs(processInfoTable);
 int lineNumber;
 for (int i = 0; i < numbers; i++)
 {
  lineNumber = i + 1;
  printf(1, "%d %d\t%s\t%d\t%s",
   lineNumber,
   processInfoTable[i].pid,
   states[processInfoTable[i].state],
   processInfoTable[i].sz,
   processInfoTable[i].name);
  printf(1, "\n");
 }
 exit();
}

A brief demonstration of what has been implemented

Launching xv6 on Windows 10 through the command line

Calling to hello, ps, sh, and kill system calls

The shutdown system call


This post is also available in Spanish "Implementar la llamada al sistema 'ps' en xv6 | Sistemas Operativos @US".

No hay comentarios:

Publicar un comentario