SLIDE 1 The Shell
What does a shell do?
- execute commands, programs
- but how?
For built in commands run some code to do the command For other commands find program executable and .... run it. Other features: wildcards, pipes, redirection.
SLIDE 2 Processes
The shell is a process used to start up other processes (parent-child). A process is a program in execution with all virtual objects (files, cpu, memory) associated with it. Process characteristics
- code to execute
- data to read/write
- resources
- a pid
SLIDE 3 System Calls
Functions to give user an interface to the kernel. POSIX system calls vs. library functions System calls are documented in section 2 of the manual.
- man -s 2 systemcall (Solaris)
- man 2 systemcall (Linux)
- systemcall(2) – denotes man page
in section 2
SLIDE 4
File Management System Calls
fd = open(file, how, options); man -s 2 open look for include files and arg types Also for return value meaning Most return -1 on an error (always check for error case and handle it appropriately) Look for what arguments mean and values they can take (constants)
SLIDE 5 File Management System Calls
O_RDONLY – open for reading O_WRONLY – open for writing O_RDWR – open for read and write O_APPEND – to append to a file O_CREAT – to create a file O_TRUNC – to truncate a file Return value is file descriptor to use,
- 1 on error (Use perror(3C) or
strerror(3C).)
SLIDE 6
File Management System Calls
s = close(fd); n = read(fd, buffer, nbytes); n = write(fd, buffer, nbytes); position = lseek(fd, offset, whence); s = stat(name, &buf); // fstat(), lstat() s = mkdir(name, mode); s = link(name1, name2); s = rmdir(name); s = unlink(name); s = chdir(dirname); s = chmod(name, mode);
SLIDE 7
File Descriptors
In POSIX, a file descriptor (fd) is an integer that is assigned when a file is open. There are 3 standard file descriptors which every process (save perhaps a daemon) should expect to have: Integer value Name Standard Input (stdin) 1 Standard Output (stdout) 2 Standard Error (stderr)
SLIDE 8
System Calls - Errors
Most system calls return a -1 on error and set errno – check the man page
Always do error checking!!!
Use perror(3C) or strerror(3C) to get more meaningful error messages from errno.
SLIDE 9 Process Mgmt System Calls
pid = fork();
- create a child process – copy of parent
pid == -1, on error pid == 0, executing in new (child) proc. else pid of child returned to parent pid = waitpid(pid, &statloc, options); exit(status);
- check return status of programs
* in tcsh 'set printexitvalue' * in csh/tcsh $status, sh/bash $?
SLIDE 10
Process Mgmt System Calls
s = kill(pid,signal); s = execve(name, argv, envp); exec(2) lists 6 functions from the exec() family of system calls. The most general is execve(). waitpid(3C), wait(3C) They can block and wait for a process to finish, or be non-blocking.
SLIDE 11
How a shell works
(to run a program) Create a child process (a copy of parent with a new pid) with fork() system call. In the child process use one of the exec(2) family of system calls to “run” the program. Parent process should then wait for the child to finish. (i.e. use waitpid()).
SLIDE 12
Using fork(2) to create a new process pid = fork(); if ( pid == -1 ) /* error */ { perror(“fork”); exit(-1); } if ( pid == 0 ) /* child */ { /* execute code for child */ } else /* parent */ { /* execute code for parent */ } /* go over example programs */
SLIDE 13 How the Shell works more How does the shell find code to run for a command? Some commands are built-in to the shell
- so no fork() needed
- some are required to be to work
(cd, fg, bg)
- some are built in for speed gain
(avoid costly fork() of new process) (e.g. Tcsh has ls-F)
- disadvantage – goes against UNIX
- changing the command
SLIDE 14 How the Shell finds executables Use the PATH environment variable
- set path, setenv PATH
- what is '.'? problems?
Use a loop to find executable file in PATH
- use strtok() on PATH
- use access(2) with X_OK
- construct path to test with snprintf()
snprintf(path, n, “%s/%s”, dir, command);
SLIDE 15
Command line arguments int main(int argc, char **argv) argv[0] – executable name argv[1] – first argument argv[n] – nth argument What about environment variables?
int main(int argc, char **argv, char** envp)
Go over exec(2) man page.
SLIDE 16
Signals, Interrupt processing Sent with kill(2) or kill(1) Ctrl-C = SIGINT Ctrl-Z = SIGTSTP SIG{HUP, USR1, USR2, SEGV} catching signals and handling them with signal() or sigset() ignore signals with sigignore() or signal(SIGINT, SIG_IGN)
SLIDE 17 Signals, Interrupt processing Signal SIGKILL (9) cannot be caught
kill -9 -1 kill -l will list signals <sys/signal.h> look at /usr/include/sys/iso/signal_iso.h look at sample signal handler code.
SLIDE 18
Thoughts on project 1 cc, gcc, make and makefiles Allocating memory with malloc(), calloc() pointers, seg faults, bus errors .h files -> /usr/include man pages gets() vs. fgets() sprintf() vs. snprintf() (avoid strcat()) strcpy() vs. strncpy()