Kesu
Kesu

Reputation: 1

MIT6.828: Why do I get a pagefault when I use pipe the first time in my xv6 operating system?

I am now self-learning mit6.828, this course is about studying operating system xv6. This system boot with initiating memory system, user environment system, trap system ,multiprocessors and a file system(a user environment that manipulate 3GB disk space). After booting up, it starts the shell interface. My system should have no problems until here as I past all the tests in previous labs and this lab except for the last test int lab5 which test the pipe function.

The shell works well with syscalls (e.g., cat, echo), and I/O redirection('<' and '>'). However, the pipe function has problem whenever I execute the first pipe command. Example:

-The result is that the system trigger a pagefault at address 0x00000070 or 0x00000000 sometimes. This address looks suspicious but I don't know why.

[00002002] SPAWN: /cat
The faulting addr is 00806000
The faulting addr is 00000070
[00002003] user panic in sh at lib/fork.c:25: pgfault: bad faulting access

-If I do an empty pipe before "echo hello | cat" command, everything works fine then.

init: running sh
init: starting sh
The parent envid is 00002003, the child envid is 00002001
$ |

The system return to shell instead fo panic because the arguments before pipe and after pipe are null arguments.

EMPTY COMMAND
[00002002] exiting gracefully

After this empty pipe, the rest of pipe commands work fine

$ echo hello | cat
hello

Below is the code of pipe in shell

case '|':   // Pipe
//   p[1]   -------->
//                  |
//   p[0]   <-------
// p[1] will be the output of the prog 1 e.g.,"echo hello",
// and p[0] will be the input of prog 2 e.g., "cat";
    if ((r = pipe(p)) < 0) {
        cprintf("pipe: %e", r);
        exit();
    }
    if (debug)
        cprintf("PIPE: %d %d\n", p[0], p[1]);
    //Create a child to execute the command after '|' e.g.,"cat"
    //The mother will execute the command before '|' e.g.,"echo hello"
    if ((r = fork()) < 0) {
        cprintf("fork: %e", r);
        exit();
    }
    //For the child process("cat"), it replaces its stdin with pipe[0].
    if (r == 0) {
        if (p[0] != 0) {
            dup(p[0], 0);
            close(p[0]);
        }
        close(p[1]);
        debug = 1;
        goto again;
    } else {
    //For the parent, it replaces its stdout with pipe[1].
        pipe_child = r;
        if (p[1] != 1) {
            dup(p[1], 1);
            close(p[1]);
        }
        close(p[0]);
        goto runit;
    }
    break;

Upvotes: 0

Views: 33

Answers (0)

Related Questions