Implement a shell by yourself--MIT xv6 Shell
This is actually a small classroom assignment as a 6.828 ...
Focus on the analysis of building ideas and processes, specific code implementation to GitHub can be found.
Https://github.com/jasonleaster/MIT_6_828_assignments_2012/blob/homework1/sh.c
-----------------------------------Everybody, I'm a split line------------------------------------------------------------------ -
Here the main implementation of the basic three types of commands
- Executable's Program Commands
- REDIRECT Command
- Pipeline command
The implementation of the "base class" (Forgive me for using this word) is a struct cmd this struct is a member that is used to record the type of command.
Three classes, "means executable program ' | ' represents the pipeline command, ' < ' and ' > ' represent the redirection type.
Each type inherits the base class, and derives the corresponding three classes of struct
struct EXECCMD
struct REDIRCMD
struct PIPECMD
For executable commands, the name of the program that primarily records executables is also available with various options parameters. So there will be char* Argv[maxargs]
For REDIRECT commands, the main record cmd is the program that triggers the redirect, for example./a.out > Tmp.txt
Then CMD is the record./a.out redirects to the file's filename char *file pointer to this file name.
For pipelines, the main record is the command on the left and right sides of the pipeline
void Runcmd (struct cmd * cmd);
This function is the core of the real driver invocation implementation shell. is responsible for invoking the system interface function EXECV (), open (), close (), DUP (), pipe () and so on a series of functions to accomplish our established goal.
The job is to complete this function.
This is a recursive function! Very interesting.
You will find that the command implementation of the shell is actually recursive haha
Here is the main function:
Call Getcmd () in the standard input to read the sizeof (BUF) size character, and then write to BUF.
The IF (buf[0] ...) is to determine if you have entered a CD command if the BUF tail is assigned a value of 0, so that buf looks like a stored string,
Then call ChDir () to replace the path specified by the string when buf+3 begins.
Then continue continues to read the command ...
If you don't change the path,
We just Fork1 () a subprocess, and the parent process waits for the subprocess to hang up ... Wait, wait. Wait, wait.
At this point, the child process starts calling Parsecmd () to parse the command string you entered ...
The ES pointer points to the end of the string, which is exactly the null character.
Then go to call ParseLine (&s, es)
ParseLine () looks too weak to be a simple package. The actual core function or Parsepipe
ExecCmd () returns a struct-cmd () struct.
The same *cmd () function will return a corresponding * struct
A special emphasis on the fun thing is that you'll find here ExecCmd () returns a struct cmd* pointer
But the ExecCmd () function does apply for a struct execcmd () struct. So here's the problem. How could that be.
Looking back at the relationship between the four structures you will find that the trick here is that their first members are the same!
A "base class" pointer was returned.
"Don't make a fuss of the year."
Implement a shell by yourself--MIT xv6 Shell