Nothing Special   »   [go: up one dir, main page]

XV6 Project

Download as pdf or txt
Download as pdf or txt
You are on page 1of 38

IMPLEMENTATION OF SHELL, EDITOR, COMMAND,

SYSTEM CALL, AND ENHANCEMENT IN XV6

A SKILLING PROJECT REPORT


Submitted towards the professional course
19CS2106S Operating Systems Design
SOBHAN SAI KURITI (190032096)

BACHELOR OF TECHNOLOGY
Branch: Computer Science and Engineering

NOVEMBER 2020

Department of Computer Science and Engineering


K L Deemed to be University,
Green Fields, Vaddeswaram,
Guntur District, A.P., 522 502.
TABLE OF CONTENTS

CHAPTER NO. TITLE

1 What is XV6?
2 SRS
3 Data Flow Diagrams
4 Modules Description
5 Codes with output
6 Conclusion
WHAT IS XV6?

Xv6 is a re-implementation of the Unix sixth edition in order to use as a learning tool.
xv6 was developed by MIT as a teaching operating system for their “6.828” course. A
vital fact about xv6 is that it contains all the core Unix concepts and has a similar
structure to Unix even though it lacks some functionality that you would expect from
a modern operating system. This is a lightweight operating system where the time to
compile is very low and it also allow remote debugging. The source code of xv6 can
be cloned to your machine as follows :

git clone git://github.com/mit-pdos/xv6-public.git 190032096-xv6


System Requirements Specification

1 Introduction
1.1 Purpose

 Run an improvised version of the MIT XV6 basic OS


 Implement most common Command Line Interface functionalities in XV6
 Enhance smooth operation of the XV6
 Ensure security for the all the documents which will be saved in XV6

1.2 Scope

With the decrease in the number of people actually learning to work with the base
OS like XV6 due to its lack of functionality even for educational purposes. We took it
upon ourselves to create a Shell in XV6 with all the functionalities which we think is
absolutely necessary for us someone to use it properly without any problem.

1.3 Overview of the system

The system focuses on improving the already existing open source XV6-public OS
distribution by MIT on GitHub and use create the basic shell functionalities like
Copying, Moving and Editing files and also to display all running process. This
means we create a basic working Editor and add extra functionalities into it while
at the same time implementing all missing common Linux commands.
2 General Requirements

 Basic XV6 – use the MIT XV6 as a base code and make it run
 Copy – Implement a copy function to copy files from one location to
another
 Move – enable moving a file from one location to another using the
function
 Head – display first 10 lines of any file
 Tail – Display last 10 lines of any file
 Editor – Create a basic editor to create and modify files
 Process Display – display all running process

3 Functional Requirements

3.1 Necessary requirements

 The user should have general computer knowledge


 The users should have a popular Linux Distribution
 User should have a virtualization command like Qemu or Qemu-KVD
 User should be comfortable with working on a sole Command-Line-
Interface without any mouse usage

3.2 Technical requirements

 Linux Distro with QEMU or any other Virtualization support must be


installed
4 Interface requirements

4.1 Software Requirements

Visual Studio Code – A basic editor for modifying the code

4.2 Hardware Requirements

 Intel core i3 processor at 2.0 GHz or higher


 256 MB RAM or higher
 256 GB Hard disk

6 Performance Requirements

 Response time of the system should be as quick as possible.


 In case of technical issues, The system should try to handle it without
entering Panic State

7 References

 XV6 MIT PDOS


 COL331/COL633 Operating Systems Course Lecture Videos
 XV6 Survival Guide
Data Flow Models
Level 0 DFD

TABLE DESCRIPTIONS
Main Memory

The RAM and HDD/SSD parts of an OS where all data is finally stored. It
does not lose any data even when the OS enters a panic state or is shut down. It
has a logical memory address or physical memory address. The RAM houses all
files which are for immediate access while the HDD/SSD houses the rest.
Buffers

The buffers are streams or intermediate storages that house all data for
display or modification. The stream 2 is connected straight to the output terminal
and is used for displaying in the Terminal. The other streams are used to carry
around information and commands from all devices and the CPU.
Structures

This Data Store stores all necessary structures required for functioning of a
CPU. This table has predefined structures and cannot be modified unless the
change is done directly to the source code. This data store houses the structures
of Process Statistics or File Structures and is used for initiation of all core
functionalities of a system.
Level 1 DFD
Level 2 DFD
MODULES DESCRIPTION

Editor
Syntax: editor file1 or bedit file1 mode
Mandatory Parameters: file1

This module is used to open a basic editor that can be used to create a new file or
view and modify an existing file. The editor can be used to insert, modify or delete
a particular line. It can also be used to insert a huge block of text. The editor can
also be used to add lines at end of the file. The editor displays the number of lines
at each line and that can be used to specify after which line you need to insert or
modify. When invoked, the editor goes to fetch the filename and if its non-
existent, it then goes on to create a file of the given name. It then prints the
whole text along with line numbers and then shows all possible options to choose
from and execute. At the end, you can choose to exit with or without saving all
changes.

Shell
A Shell provides you with an interface to the Unix system. It gathers input from
you and executes programs based on that input. When a program finishes
executing, it displays that program's output. Shell is an environment in which we
can run our commands, programs, and shell scripts. There are different flavors of
a shell, just as there are different flavors of operating systems. Each flavor of shell
has its own set of recognized commands and functions.
Shell Prompt
The prompt, $, which is called the command prompt, is
issued by the shell. While the prompt is displayed, you can type a command. Shell
reads your input after you press Enter. It determines the command you want
executed by looking at the first word of your input. A word is an unbroken set of
characters. Spaces and tabs separate words.
Change Directory (CD)
Syntax: cd [OPTIONS] directory

The cd (“change directory”) command is used to change the current working


directory in Linux and other Unix-like operating systems. It is one of the most
basic and frequently used commands when working on the Linux terminal. The
current working directory is the directory (folder) in which the user is currently
working in. Each time you interact with your command prompt, you are working
within a directory.

Change Priority (CHPR)


Priority scheduling is a non-primitive algorithm and one of the most common
scheduling algorithms in batch systems. Each process is assigned a priority.
Process with highest priority is to be executed first and so on. Processes with
same priority are executed on first come first served basis.

Demonstrate Virtual Memory In XV6 Memory management is one of the most


important features of any operating system. In this assignment we will examine
how xv6 handles memory and attempt to extend it by implementing a paging
infrastructure which will allow xv6 to store parts of the process' memory in a
secondary storage. • Virtual memory create an illusion to the programmer that
has large memory even though computer had limited RAM size. • VM divided into
pages and size of each page is 4KB
CODES WITH OUTPUT
Shell.c

Code :

// Shell.
#include "types.h"
#include "user.h"
#include "fcntl.h"

// Parsed command representation


#define EXEC 1
#define REDIR 2
#define PIPE 3
#define LIST 4
#define BACK 5

#define MAXARGS 10

struct cmd {
int type;
};

struct execcmd {
int type;
char *argv[MAXARGS];
char *eargv[MAXARGS];
};

struct redircmd {
int type;
struct cmd *cmd;
char *file;
char *efile;
int mode;
int fd;
};

struct pipecmd {
int type;
struct cmd *left;
struct cmd *right;
};

struct listcmd {
int type;
struct cmd *left;
struct cmd *right;
};

struct backcmd {
int type;
struct cmd *cmd;
};

int fork1(void); // Fork but panics on failure.


void panic(char*);
struct cmd *parsecmd(char*);

// Execute cmd. Never returns.


void
runcmd(struct cmd *cmd)
{
int p[2];
struct backcmd *bcmd;
struct execcmd *ecmd;
struct listcmd *lcmd;
struct pipecmd *pcmd;
struct redircmd *rcmd;

if(cmd == 0)
exit();

switch(cmd->type){
default:
panic("runcmd");

case EXEC:
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0)
exit();
exec(ecmd->argv[0], ecmd->argv);
printf(2, "exec %s failed\n", ecmd->argv[0]);
break;

case REDIR:
rcmd = (struct redircmd*)cmd;
close(rcmd->fd);
if(open(rcmd->file, rcmd->mode) < 0){
printf(2, "open %s failed\n", rcmd->file);
exit();
}
runcmd(rcmd->cmd);
break;

case LIST:
lcmd = (struct listcmd*)cmd;
if(fork1() == 0)
runcmd(lcmd->left);
wait();
runcmd(lcmd->right);
break;

case PIPE:
pcmd = (struct pipecmd*)cmd;
if(pipe(p) < 0)
panic("pipe");
if(fork1() == 0){
close(1);
dup(p[1]);
close(p[0]);
close(p[1]);
runcmd(pcmd->left);
}
if(fork1() == 0){
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
runcmd(pcmd->right);
}
close(p[0]);
close(p[1]);
wait();
wait();
break;

case BACK:
bcmd = (struct backcmd*)cmd;
if(fork1() == 0)
runcmd(bcmd->cmd);
break;
}
exit();
}

int
getcmd(char *buf, int nbuf)
{
printf(2, "$ ");
memset(buf, 0, nbuf);
gets(buf, nbuf);
if(buf[0] == 0) // EOF
return -1;
return 0;
}

char* strcat(char* s1,char *s2)


{
char *b=s1;
while(*s1) ++s1;
while(*s2) *s1++ = *s2++;
*s1=0;
return b;
}

int
main(void)
{
static char buf[100],bufx[100];
int fd;

// Ensure that three file descriptors are open.


while((fd = open("console", O_RDWR)) >= 0){
if(fd >= 3){
close(fd);
break;
}
}
int err=open("temp.pwd",O_CREATE|O_RDWR);
write(err,"/",1);
close(err);
// Read and run input commands.
while(getcmd(buf, sizeof(buf)) >= 0){
memset(bufx,'\0',sizeof(bufx));
if(strlen(buf)>1) bufx[0]='/';
strcat(bufx,buf);
//printf(1,"%s\n",bufx);
if(bufx[1] == 'c' && bufx[2] == 'd' && bufx[3] == ' '){
// Chdir must be called by the parent, not the child.
bufx[strlen(bufx)-1] = 0; // chop \n
if(bufx[strlen(bufx)-1]=='/') bufx[strlen(bufx)-1]='\0';
if(chdir(bufx+4) < 0)
{
printf(2, "cannot cd %s\n", bufx+4);
}
else
{
err=open("/temp.pwd",O_RDWR);
char temp[100];
int e=read(err,temp,sizeof(temp));
if(e<0) exit();
if(strcmp(bufx+4,".")==0) continue;
if(strcmp(bufx+4,"..")==0)
{
temp[strlen(temp)-1]='\0';
int nn=strlen(temp)-1;
while(temp[nn]!='/'){
temp[nn]='\0';
//printf(1,"%s ",temp);
nn--;
}
unlink("/temp.pwd");
int err2=open("/temp.pwd",O_CREATE|O_RDWR);
write(err2,temp,1);
close(err2);
//printf(1,"%s\n",temp);
continue;
}
strcat(bufx,"/");
write(err,bufx+4,strlen(bufx)-4);
close(err);
//printf(1,"~~ %s\n",bufx+4);
}
continue;
}
if(fork1() == 0)
runcmd(parsecmd(bufx));
wait();
}
exit();
}
void
panic(char *s)
{
printf(2, "%s\n", s);
exit();
}

int
fork1(void)
{
int pid;

pid = fork();
if(pid == -1)
panic("fork");
return pid;
}

//PAGEBREAK!
// Constructors

struct cmd*
execcmd(void)
{
struct execcmd *cmd;

cmd = malloc(sizeof(*cmd));
memset(cmd, 0, sizeof(*cmd));
cmd->type = EXEC;
return (struct cmd*)cmd;
}

struct cmd*
redircmd(struct cmd *subcmd, char *file, char *efile, int mode, int fd)
{
struct redircmd *cmd;

cmd = malloc(sizeof(*cmd));
memset(cmd, 0, sizeof(*cmd));
cmd->type = REDIR;
cmd->cmd = subcmd;
cmd->file = file;
cmd->efile = efile;
cmd->mode = mode;
cmd->fd = fd;
return (struct cmd*)cmd;
}

struct cmd*
pipecmd(struct cmd *left, struct cmd *right)
{
struct pipecmd *cmd;

cmd = malloc(sizeof(*cmd));
memset(cmd, 0, sizeof(*cmd));
cmd->type = PIPE;
cmd->left = left;
cmd->right = right;
return (struct cmd*)cmd;
}

struct cmd*
listcmd(struct cmd *left, struct cmd *right)
{
struct listcmd *cmd;

cmd = malloc(sizeof(*cmd));
memset(cmd, 0, sizeof(*cmd));
cmd->type = LIST;
cmd->left = left;
cmd->right = right;
return (struct cmd*)cmd;
}

struct cmd*
backcmd(struct cmd *subcmd)
{
struct backcmd *cmd;

cmd = malloc(sizeof(*cmd));
memset(cmd, 0, sizeof(*cmd));
cmd->type = BACK;
cmd->cmd = subcmd;
return (struct cmd*)cmd;
}
//PAGEBREAK!
// Parsing

char whitespace[] = " \t\r\n\v";


char symbols[] = "<|>&;()";

int
gettoken(char **ps, char *es, char **q, char **eq)
{
char *s;
int ret;

s = *ps;
while(s < es && strchr(whitespace, *s))
s++;
if(q)
*q = s;
ret = *s;
switch(*s){
case 0:
break;
case '|':
case '(':
case ')':
case ';':
case '&':
case '<':
s++;
break;
case '>':
s++;
if(*s == '>'){
ret = '+';
s++;
}
break;
default:
ret = 'a';
while(s < es && !strchr(whitespace, *s) && !strchr(symbols, *s))
s++;
break;
}
if(eq)
*eq = s;

while(s < es && strchr(whitespace, *s))


s++;
*ps = s;
return ret;
}

int
peek(char **ps, char *es, char *toks)
{
char *s;

s = *ps;
while(s < es && strchr(whitespace, *s))
s++;
*ps = s;
return *s && strchr(toks, *s);
}

struct cmd *parseline(char**, char*);


struct cmd *parsepipe(char**, char*);
struct cmd *parseexec(char**, char*);
struct cmd *nulterminate(struct cmd*);

struct cmd*
parsecmd(char *s)
{
char *es;
struct cmd *cmd;

es = s + strlen(s);
cmd = parseline(&s, es);
peek(&s, es, "");
if(s != es){
printf(2, "leftovers: %s\n", s);
panic("syntax");
}
nulterminate(cmd);
return cmd;
}

struct cmd*
parseline(char **ps, char *es)
{
struct cmd *cmd;

cmd = parsepipe(ps, es);


while(peek(ps, es, "&")){
gettoken(ps, es, 0, 0);
cmd = backcmd(cmd);
}
if(peek(ps, es, ";")){
gettoken(ps, es, 0, 0);
cmd = listcmd(cmd, parseline(ps, es));
}
return cmd;
}

struct cmd*
parsepipe(char **ps, char *es)
{
struct cmd *cmd;

cmd = parseexec(ps, es);


if(peek(ps, es, "|")){
gettoken(ps, es, 0, 0);
cmd = pipecmd(cmd, parsepipe(ps, es));
}
return cmd;
}

struct cmd*
parseredirs(struct cmd *cmd, char **ps, char *es)
{
int tok;
char *q, *eq;

while(peek(ps, es, "<>")){


tok = gettoken(ps, es, 0, 0);
if(gettoken(ps, es, &q, &eq) != 'a')
panic("missing file for redirection");
switch(tok){
case '<':
cmd = redircmd(cmd, q, eq, O_RDONLY, 0);
break;
case '>':
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
break;
case '+': // >>
cmd = redircmd(cmd, q, eq, O_WRONLY|O_CREATE, 1);
break;
}
}
return cmd;
}

struct cmd*
parseblock(char **ps, char *es)
{
struct cmd *cmd;

if(!peek(ps, es, "("))


panic("parseblock");
gettoken(ps, es, 0, 0);
cmd = parseline(ps, es);
if(!peek(ps, es, ")"))
panic("syntax - missing )");
gettoken(ps, es, 0, 0);
cmd = parseredirs(cmd, ps, es);
return cmd;
}

struct cmd*
parseexec(char **ps, char *es)
{
char *q, *eq;
int tok, argc;
struct execcmd *cmd;
struct cmd *ret;

if(peek(ps, es, "("))


return parseblock(ps, es);

ret = execcmd();
cmd = (struct execcmd*)ret;

argc = 0;
ret = parseredirs(ret, ps, es);
while(!peek(ps, es, "|)&;")){
if((tok=gettoken(ps, es, &q, &eq)) == 0)
break;
if(tok != 'a')
panic("syntax");
cmd->argv[argc] = q;
cmd->eargv[argc] = eq;
argc++;
if(argc >= MAXARGS)
panic("too many args");
ret = parseredirs(ret, ps, es);
}
cmd->argv[argc] = 0;
cmd->eargv[argc] = 0;
return ret;
}

// NUL-terminate all the counted strings.


struct cmd*
nulterminate(struct cmd *cmd)
{
int i;
struct backcmd *bcmd;
struct execcmd *ecmd;
struct listcmd *lcmd;
struct pipecmd *pcmd;
struct redircmd *rcmd;
if(cmd == 0)
return 0;

switch(cmd->type){
case EXEC:
ecmd = (struct execcmd*)cmd;
for(i=0; ecmd->argv[i]; i++)
*ecmd->eargv[i] = 0;
break;

case REDIR:
rcmd = (struct redircmd*)cmd;
nulterminate(rcmd->cmd);
*rcmd->efile = 0;
break;

case PIPE:
pcmd = (struct pipecmd*)cmd;
nulterminate(pcmd->left);
nulterminate(pcmd->right);
break;

case LIST:
lcmd = (struct listcmd*)cmd;
nulterminate(lcmd->left);
nulterminate(lcmd->right);
break;

case BACK:
bcmd = (struct backcmd*)cmd;
nulterminate(bcmd->cmd);
break;
}
return cmd;
}

Output :
Editor.c

Code :

#include "types.h"

#include "stat.h"
#include "user.h"
#include "fcntl.h"
#include "fs.h"

#define BUF_SIZE 256
#define MAX_LINE_NUMBER 256
#define MAX_LINE_LENGTH 256
#define NULL 0

char* strcat_n(char* dest, char* src, int len);
int get_line_number(char *text[]);
void show_text(char *text[]);
void com_ins(char *text[], int n, char *extra);
void com_mod(char *text[], int n, char *extra);
void com_del(char *text[], int n);
void com_help(char *text[]);
void com_save(char *text[], char *path);
void com_exit(char *text[], char *path);
int stringtonumber(char* src);

//???????
int changed = 0;
int auto_show = 1;

int main(int argc, char *argv[])
{
    //setProgramStatus(EDITOR);
    if (argc == 1)
    {
        printf(1, "please input the command as [editor file_name]\n");
        //setProgramStatus(SHELL);
        exit();
    }
    //??????
    
    char *text[MAX_LINE_NUMBER] = {};
    text[0] = malloc(MAX_LINE_LENGTH);
    memset(text[0], 0, MAX_LINE_LENGTH);
    //?????????,?0?????line_number == x,??text[0]?text[x]??
    int line_number = 0;
    //??????
    int fd = open(argv[1], O_RDONLY);
    //??????,???????????
    if (fd != -1)
    {
        printf(1, "file exist\n");
        char buf[BUF_SIZE] = {};
        int len = 0;
        while ((len = read(fd, buf, BUF_SIZE)) > 0)
        {
            int i = 0;
            int next = 0;
            int is_full = 0;
            while (i < len)
            {
                //??"\n"?????
                for (i = next; i < len && buf[i] != '\n'; i++)
                    ;
                strcat_n(text[line_number], buf+next, i-next);
                //???????
                if (i < len && buf[i] == '\n')
                {
                    if (line_number >= MAX_LINE_NUMBER - 1)
                        is_full = 1;
                    else
                    {
                        line_number++;
                        text[line_number] = malloc(MAX_LINE_LENGTH);
                        memset(text[line_number], 0, MAX_LINE_LENGTH);
                    }
                }
                if (is_full == 1 || i >= len - 1)
                    break;
                else
                    next = i + 1;
            }
            if (is_full == 1)
                break;
        }
        close(fd);
    } else{
        printf(1,"File do not exist\n");
        exit();
    }
    
    //??????
    show_text(text);
    //????
    com_help(text);
    
    //????
    char input[MAX_LINE_LENGTH] = {};
    while (1)
    {
        printf(1, "\nplease input command:\n");
        memset(input, 0, MAX_LINE_LENGTH);
        gets(input, MAX_LINE_LENGTH);
        int len = strlen(input);
        input[len-1] = '\0';
        len --;
        //??????????
        int pos = MAX_LINE_LENGTH - 1;
        int j = 0;
        for (; j < 8; j++)
        {
            if (input[j] == ' ')
            {
                pos = j + 1;
                break;
            }
        }
        //ins
        if (input[0] == 'i' && input[1] == 'n' && input[2] == 's')
        {
            if (input[3] == '-'&&stringtonumber(&input[4])>=0)
            {
                com_ins(text, stringtonumber(&input[4]), &input[pos]);
                                 //??????????
                line_number = get_line_number(text);
            }
            else if(input[3] == ' '||input[3] == '\0')
            {
                com_ins(text, line_number+1, &input[pos]);
                                line_number = get_line_number(text);
            }
            else
            {
                printf(1, "invalid command.\n");
                com_help(text);
            }
        }
        //mod
        else if (input[0] == 'm' && input[1] == 'o' && input[2] == 'd')
        {
            if (input[3] == '-'&&stringtonumber(&input[4])>=0)
                com_mod(text, atoi(&input[4]), &input[pos]);
            else if(input[3] == ' '||input[3] == '\0')
                com_mod(text, line_number + 1, &input[pos]);
            else
            {
                printf(1, "invalid command.\n");
                com_help(text);
            }
        }
        //del
        else if (input[0] == 'd' && input[1] == 'e' && input[2] == 'l')
        {
            if (input[3] == '-'&&stringtonumber(&input[4])>=0)
            {
                com_del(text, atoi(&input[4]));
                                //??????????
                line_number = get_line_number(text);
            }   
            else if(input[3]=='\0')
            {
                com_del(text, line_number + 1);
                line_number = get_line_number(text);
            }
            else
            {
                printf(1, "invalid command.\n");
                com_help(text);
            }
            
        }
        else if (strcmp(input, "show") == 0)
        {
            auto_show = 1;
            printf(1, "enable show current contents after text changed.\n");
        }
        else if (strcmp(input, "hide") == 0)
        {
            auto_show = 0;
            printf(1, "disable show current contents after text changed.\n");
        }
        else if (strcmp(input, "help") == 0)
            com_help(text);
        else if (strcmp(input, "save") == 0 || strcmp(input, "CTRL+S\n") == 0)
            com_save(text, argv[1]);
        else if (strcmp(input, "exit") == 0)
            com_exit(text, argv[1]);
        else
        {
            printf(1, "invalid command.\n");
            com_help(text);
        }
    }
    //setProgramStatus(SHELL);
    
    exit();
}

//??src??n????dest
char* strcat_n(char* dest, char* src, int len)
{
    if (len <= 0)
        return dest;
    int pos = strlen(dest);
    if (len + pos >= MAX_LINE_LENGTH)
        return dest;
    int i = 0;
    for (; i < len; i++)
        dest[i+pos] = src[i];
    dest[len+pos] = '\0';
    return dest;
}

void show_text(char *text[])
{
    printf(1, "****************************************\n");
    printf(1, "the contents of the file are:\n");
    int j = 0;
    for (; text[j] != NULL; j++)
        printf(1, "%d%d%d:%s\n", (j+1)/100, ((j+1)%100)/10, (j+1)%10, text[j]);
}

//?????????,?0??,?return x??text[0]?text[x]??
int get_line_number(char *text[])
{
    int i = 0;
    for (; i < MAX_LINE_NUMBER; i++)
        if (text[i] == NULL)
            return i - 1;
    return i - 1;
}

int stringtonumber(char* src)
{
    int number = 0; 
    int i=0;
    int pos = strlen(src);
    for(;i<pos;i++)
    {
        if(src[i]==' ') break;
        if(src[i]>57||src[i]<48) return -1;
        number=10*number+(src[i]-48);
    }
    return number;
}

//????,n????????,?1??
//extra:??????????,????????
void com_ins(char *text[], int n, char *extra)
{
    if (n < 0 || n > get_line_number(text) + 1)
    {
        printf(1, "invalid line number\n");
        return;
    }
    char input[MAX_LINE_LENGTH] = {};
    if (*extra == '\0')
    {
        printf(1, "please input content:\n");
        gets(input, MAX_LINE_LENGTH);
        input[strlen(input)-1] = '\0';
    }
    else
        strcpy(input, extra);
    int i = MAX_LINE_NUMBER - 1;
    for (; i > n; i--)
    {
        if (text[i-1] == NULL)
            continue;
        else if (text[i] == NULL && text[i-1] != NULL)
        {
            text[i] = malloc(MAX_LINE_LENGTH);
            memset(text[i], 0, MAX_LINE_LENGTH);
            strcpy(text[i], text[i-1]);
        }
        else if (text[i] != NULL && text[i-1] != NULL)
        {
            memset(text[i], 0, MAX_LINE_LENGTH);
            strcpy(text[i], text[i-1]);
        }
    }
    if (text[n] == NULL)
    {
        text[n] = malloc(MAX_LINE_LENGTH);
        if (text[n-1][0] == '\0')
        {
            memset(text[n], 0, MAX_LINE_LENGTH);
            strcpy(text[n-1], input);
            changed = 1;
            if (auto_show == 1)
                show_text(text);
            return;
        }
    }
    memset(text[n], 0, MAX_LINE_LENGTH);
    strcpy(text[n], input);
    changed = 1;
    if (auto_show == 1)
        show_text(text);
}

//????,n????????,?1??
//extra:??????????,?????????
void com_mod(char *text[], int n, char *extra)
{
    if (n <= 0 || n > get_line_number(text) + 1)
    {
        printf(1, "invalid line number\n");
        return;
    }
    char input[MAX_LINE_LENGTH] = {};
    if (*extra == '\0')
    {
        printf(1, "please input content:\n");
        gets(input, MAX_LINE_LENGTH);
        input[strlen(input)-1] = '\0';
    }
    else
        strcpy(input, extra);
    memset(text[n-1], 0, MAX_LINE_LENGTH);
    strcpy(text[n-1], input);
    changed = 1;
    if (auto_show == 1)
        show_text(text);
}

//????,n????????,?1??
void com_del(char *text[], int n)
{
    if (n <= 0 || n > get_line_number(text) + 1)
    {
        printf(1, "invalid line number\n");
        return;
    }
    memset(text[n-1], 0, MAX_LINE_LENGTH);
    int i = n - 1;
    for (; text[i+1] != NULL; i++)
    {
        strcpy(text[i], text[i+1]);
        memset(text[i+1], 0, MAX_LINE_LENGTH);
    }
    if (i != 0)
    {
        free(text[i]);
        text[i] = 0;
    }
    changed = 1;
    if (auto_show == 1)
        show_text(text);
}
void com_help(char *text[])
{
    printf(1, "****************************************\n");
    printf(1, "instructions for use:\n");
    printf(1, "ins-n, insert a line after line n\n");
    printf(1, "mod-n, modify line n\n");
    printf(1, "del-n, delete line n\n");
    printf(1, "ins, insert a line after the last line\n");
    printf(1, "mod, modify the last line\n");
    printf(1, "del, delete the last line\n");
    printf(1, "show, enable show current contents after executing a command.\n");
    printf(1, "hide, disable show current contents after executing a command.\n");
    printf(1, "save, save the file\n");
    printf(1, "exit, exit editor\n");
}

void com_save(char *text[], char *path)
{
    //??????
    unlink(path);
    //???????
    int fd = open(path, O_WRONLY|O_CREATE);
    if (fd == -1)
    {
        printf(1, "save failed, file can't open:\n");
        //setProgramStatus(SHELL);
        exit();
    }
    if (text[0] == NULL)
    {
        close(fd);
        return;
    }
    //???
    write(fd, text[0], strlen(text[0]));
    int i = 1;
    for (; text[i] != NULL; i++)
    {
        printf(fd, "\n");
        write(fd, text[i], strlen(text[i]));
    }
    close(fd);
    printf(1, "saved successfully\n");
    changed = 0;
    return;
}

void com_exit(char *text[], char *path)
{
    //??????
    while (changed == 1)
    {
        printf(1, "save the file? y/n\n");
        char input[MAX_LINE_LENGTH] = {};
        gets(input, MAX_LINE_LENGTH);
        input[strlen(input)-1] = '\0';
        if (strcmp(input, "y") == 0)
            com_save(text, path);
        else if(strcmp(input, "n") == 0)
            break;
        else
        printf(2, "wrong answer?\n");
    }
    //????
    int i = 0;
    for (; text[i] != NULL; i++)
    {
        free(text[i]);
        text[i] = 0;
    }
    //??
    //setProgramStatus(SHELL);
    exit();
}

Output:
cd

code:

#include "types.h"
#include "stat.h"
#include "user.h"

int main(int argc,char *argv[])


{
if(argc<2)
{
exit();
}
if(chdir(argv[1])!= 0)
{
exit();
}
exit();
}

Output :
chpr

Code :

Adding Chpr into system calls like syscall.c, syscall.h, user.h, usys.S, defs.h, proc.c,
sysproc.c and adding ps, dpro, nice codes

int chpr(int pid, int priority) {


struct proc *p;
acquire(&ptable.lock);
for(p = ptable.proc; p < &ptable.proc[NPROC]; p++)
{
if(p->pid == pid)
{
p->priority = priority;
break;
}
}
release(&ptable.lock);
return pid;
}

Output:

IN NEXT PAGE
VM.C

Code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define PSIZE 4096
int main(int argc, char *argv[])
{
int addressFile,backingStore;
char *file= argv[1];
char ch,ct, input[1000], output;
int logicalAddress, physicalAddress;
int i=0, j=0;
int p,d;

int f;
char frames[PSIZE*16];
int frametable[16];
int start, current;
int offset, pagefault=0;
int freeFrame=-1;
int pagetable[16];
for (j=0;j<16;j++)
{
pagetable[j] = -1;
}
pagetable[0]=0x2;
pagetable[1]=0x1;
pagetable[2]=0x6;
pagetable[3]=0x0;
pagetable[4]=0x4;
pagetable[5]=0x3;
pagetable[9]=0x5;
pagetable[11]=0x7;
for (j=0;j<16;j++)
{
frametable[j] = -1;
}
frametable[0] = 1;
frametable[1] = 1;
frametable[2] = 1;
frametable[3] = 1;
frametable[4] = 1;
frametable[5] = 1;
frametable[9] = 1;
frametable[11] = 1;
addressFile = open("address.txt",O_RDONLY);
backingStore = open("BACKING_STORE.bin",O_RDONLY);
if(addressFile != -1)
{
while(read(addressFile, &ch, sizeof(char)) != 0)
{
if(ch != '\n')
{
input[i] = ch;
i++;
}
else
{
logicalAddress =atoi(input);
p = (logicalAddress & 0x000000000000f000UL) >> 12;
d = (logicalAddress & 0x0000000000000fffUL);

printf("\nlogicalAddress: %d, p: %d, d: %d",


logicalAddress,p,d);
if(pagetable[p]!= -1){

f = pagetable[p];
physicalAddress = (f * PSIZE) + d;
printf("\nphysicalAddress: %d, f: %d",
physicalAddress,f);

}
// pagetable-miss, page-fault
else
{
pagefault++;
// locate free frame (-1) in physical memory
for (j=0;j<8;j++)
{
if(frametable[j]==-1)
{
freeFrame = j;
break;
}
}
if(backingStore != -1)
{

offset=0;
start = PSIZE * p;
current=lseek(backingStore, start,
SEEK_SET);
while((offset < PSIZE)&&(current))
{
current = read(backingStore, &ct,
sizeof(char));
frames[freeFrame*offset] = ct;
offset++;

}
}
else
{
printf("Backing-Store Does not exist!");
close(backingStore);
close(addressFile);
return 0;
}
// update pagetable, frametable
pagetable[p] = freeFrame;
frametable[freeFrame] = 0;

physicalAddress = (freeFrame * PSIZE) + d;


printf("\nphysicalAddress: %d, freeFrame: %d",
physicalAddress, freeFrame);
}

output = frames[physicalAddress];
printf("\nByte value stored at physicalAddress %d: %c\
n",physicalAddress, output);
memset(input,0,sizeof(input));
i=0;

}
}
printf("\nTotal Page Faults: %d",pagefault);
}
else
printf("Addresses File Does not exist!");

close(backingStore);
close(addressFile);
return 0;
}

IN ADDITION TO THESE WE HAVE TO ADD address.txt BACKING_STORE.bin a.out


pagetable.c

Output:
CONCLUSION

We successfully created a basic XV6 shell with what our team believes to be
necessary for a common usage. We learnt a lot from working with a basic
Operating System and would like to thank everyone for this opportunity. The
journey to modifying the XV6 and implementing our own shell was a very
interesting and eventful one and even though sometimes, our code was like a
shot in the dark, we believe that we achieved what we wanted to in the end.

You might also like