360 likes | 467 Views
Week 2 The Crunchy Shell to the Soft and Chewy Kernel…. Sarah Diesburg 8/3/2010 COP4610 / CGS5765. Why is the Shell Important?. Shells provide us with a way to interact with the core system Executes programs on our behalf Shows us our stuff No OS should be without one!
E N D
Week 2 The Crunchy Shell to the Soft and Chewy Kernel… Sarah Diesburg 8/3/2010 COP4610 / CGS5765
Why is the Shell Important? • Shells provide us with a way to interact with the core system • Executes programs on our behalf • Shows us our stuff • No OS should be without one! • Can think of a shell as “built around” a component • So what are some examples of shells?
How do we Crack the Shell? • In other words, how will our shell interact with the soft and chewy kernel? • /proc file system • System calls
What is /proc? • Virtual file system created to pass information via files to and from the kernel • Inside /proc directory • Often used in kernel debugging or when a developer does not want to create a new system call
Why /proc? • You will be reading and displaying a bunch of goodies from the kernel through the /proc interface • Date • Up Time • Idle Time • CPU Info • Memory Info • Kernel Version • Terminal Process Details
How /proc? • Looking to our good friend bash… $> cat /proc/cpuinfo • (Hint – your viewproc command should do something similar…)
System Calls • What are they again? • The traditional way to ask the OS to do something on the user’s behalf • Some important ones • Fork() • Execv()
Inside main() • Continuous loop • Parse user input • Make something happen
Inside main() while(1) { }
Inside main() while(1) { */ Get user input */ }
Inside main() while(1) { */ Get user input */ */ Exit? */ }
Inside main() while(1) { */ Get user input */ */ Exit? */ */ Do something with input */ }
Inside main() while(1) { */ Get user input */ */ Exit? */ */ Do something with input */ */ Reset the shell */ }
I/O Streams • Examples • scanf() reads from standard input • fscanf() reads from any I/O stream • printf() prints to standard output • fprintf() prints to any I/O stream
Environmental Variables • Gives programs specific information about your environemnt, such as your execution paths sarah@trogdor:~$ echo $PATH /usr/local/bin:/usr/bin:/bin:/usr/games • May be set by you or other shell scripts (like .bashrc) sarah@trogdor:~$ export TEST=hello sarah@trogdor:~$ echo $TEST hello
Environmental Variables char *getenv(const char *name); • Returns value of an environmental variable • Returns NULL if not found
Environmental Variables • Important examples • $PATH • $USER • $PWD • (Hint: may want to use these in building the shell prompt)
Command Line Parsing • Standard input (stdin) is the source of input data for command line programs • Parsing can be done in multiple stages • Strip the whitespace • Interpret the command • Resolve the pathname • Variable expansion • I/O redirection • Final execution
Parsing Example Too much whitespace! ls -l a
Parsing Example ls -l a ls –la Parse out the whitespace
Parsing Example ls -l a ls –la /bin/ls -la Resolve the pathname
Resolving Pathnames? • You may not just pass ‘ls’ to the execute command • What is ‘ls’? • You must search all of the users paths stored in the $PATH environmental variable
Finding full pathname for ‘ls’ $PATH=/usr/local/bin:/usr/bin:/bin • Does /usr/local/bin/ls exist? • No • Does /usr/bin/ls exist? • No • Does /bin/ls exist? • Yes!
Processes • Our shell process must continually run • …but we need to execute other stuff on the user’s behalf • How can we create “children” processes to do our work? • Fork!
Fork • Child pid==0 • Parent pid==something else #include <stdio.h> #include <unistd.h> #include <sys/types.h> int main() { pid_tpid; if ((pid = fork()) == 0) { printf(“I am a child with pid %d\n”, pid); } else { printf(“I am the parent with pid %d\n”, pid); } return 0; }
Exec • Once we have created a child process, we need the child to execute a command for us • Exec has many forms • Execl • Execlp • Execle • Execv • Execvp • Must use execv() for project 1!
Execv() • Takes two arguments • Absolute pathname • Array of string arguments, ending with NULL • What is an absolute pathname? • Full execution path starting from root “/” • /bin/ls
Execv() char *command = “/bin/ls”; char *argv[] = {“/bin/ls”, “-l”, NULL}; execv(command,argv); • Execv() replaces running image of child with a new process!
Wait up? • How does our parent process know to wait until the child is done? • waitpid() • Performing a wait allows the system to release the resources associated with the child • If child is not waitedon, it will become a zombie!
Zombie? • Process that shows up with a “Z” status or the word <defunct> • Child process has terminated, but parent has not waited on it • Child process stays allocated on the system until • Wait() or waitpid() is called by the parent • The parent exits, and init “adopts” the zombie processes and performs a wait()
waitpid() int waitpid(pid_t pid, int *status, int options); • pid – type of children to wait on • For this project, pid==0 to mean wait for any child process created by our parent • *status – returns the status of the child process • options – return if additional things have happened to the child
waitpid() • Comment waitpid() line to see a defunct process for 10 seconds through ‘ps’ #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> int main() { pid_tpid; if ((pid = fork()) == 0) { printf(“I am a child with pid %d\n”, pid); } else { printf(“I am the parent\n”); waitpid(-1, status, 0); sleep(10); } return 0; }
In Summary • Pieces necessary for some of project 1 • Part 1 – Command line parsing • Part 2 – Environmental variables and expansion • Part 3 – Command execution • Part 7 – Built-ins including /proc • Hint: chdir() may be of some use • Part 8 – The prompt via parsing environmental variables and updating $PWD
Next Recitation • Part 4 – Input/output redirection • Part 5 – Pipes • Part 6 – Background processing
Any Questions? • Time for some of my demos?