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.
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
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
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)
File Management System Calls open(2) some more 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).)
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);
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 0 Standard Input (stdin) 1 Standard Output (stdout) 2 Standard Error (stderr)
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.
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 $?
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.
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()).
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 */
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
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);
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.
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)
Signals, Interrupt processing Signal SIGKILL (9) cannot be caught or ignored. 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.
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()
Recommend
More recommend