530 likes | 676 Views
The Process . CIS 370, Fall 2009 CIS UMassD. The notion of a process. In UNIX a process is an instance of a program in execution A job or a task Each process has program code, data segment, program stack etc.
E N D
The Process CIS 370, Fall 2009 CIS UMassD
The notion of a process • In UNIX a process is an instance of a program in execution • A job or a task • Each process has program code, data segment, program stack etc. • The shell (or any command interpreter) starts a process for each command submitted.
Process examples • $ cat file1 file2 • results in the shell creating a process specifically for running this command • $ ls | wc • results in the shell creating two processes where the output of ls is sent (via the pipe) as in input to wc • Processes are different from programs • a single program may create several processes.
How to create a process • UNIX provides several mechanisms for creating processes. • fork - creates a new process by duplicating the calling process. • exec - perform the transformation of a process by overlaying its memory space with a new program. • wait - provides the ability for a process to be halted while a related process finishes. • exit - used to terminate a process.
The fork system call • Usage : #include <sys/types.h> #include <unistd.h> pid_t fork(void); • A successful call will result in the creation of a new process that is more or less identical to the calling process.
The Process • The newly created process is called as the child process and the process that made the call is called as the parent process. • After the system call is made successfully both processes begin execution at the statement after the call to fork. • Both processes will have identical data and code segments. All the variable will have the same value as before the fork call.
PC PC PC PC OUTPUT printf(“one\n”); pid = fork(); printf(“two\n”); $ one $ two $ two Before fork() After printf(“one\n”); pid = fork(); printf(“two\n”); printf(“one\n”); pid = fork(); printf(“two\n”);
Process IDs • fork() returns two values, unlike most system calls. • fork() returns the process id of the newly created process to the parent. • fork() returns a 0 to the newly created process. • Since all the variables are common, this can be used to synchronize and distinguish the child process from the parent process.
The exec family of calls • Unlike fork, exec will replace the calling process. • fork replicates the calling process, exec will create a new process and destroys the called process. The new process will inherit the process id of the called process. • What is the point? What is interesting about simply the same process over and over again?
PC PC PC printf (…) execl(“bin/ls”,…) Before exec After 1st line of ls
Data and File Sharing in fork • In fork(), an identical copy of the parent process is made. • All the variables are identical and all files open in the parent will remain open in the child process. • Since the child process occupies a different memory location, modifications are local. • Open files are are however different. The read-write pointer is maintained by the OS.
Data and File Sharing in exec • Open file descriptors are also passed across exec calls. • The read-write pointer remains in the same position as in the process that called exec. • What about variables and their values? • The system call fcntl can be used to set the close-on-exec flag. When this flag is set the file is closed when the exec calls is made.
#include<fcntl.h> int fd; fd = open(“file”, O_RDONLY); . /* set close-on-exec flag on */ fcntl(fd, F_SETFD, 1); /*set close-on-exec flag off */ fcntl (fd, F_SETFD, 0); /* the value can be obtained as follows */ res = fcntl(fd, F_GETFD, 0);
Terminating a process - exit • Usage #include < stdlib.h> void exit(int status);
Synchronizing Processes - the wait system call • Usage #include<sys/types.h> #include<sys/wait.h> pid_t wait (int *status); wait() temporarily suspends the process till its child process finishes execution.
More on wait • The call to wait returns the process id of the child process that exits • The argument to wait is an integer pointer that contains the exit code of the exiting child process. • If there are n child processes, n wait statements would be needed if the parent is to continue after all the child processes have exited.
Waiting for a specific child • Usage #include<sys/types.h> #include<sys/wait.h> pid_t waitpid(pid_t pid, int *status, int options); • The first argument specifies the id of the process the parent is waiting for (if this is set to -1 and the options to 0, this call behaves exactly like wait() ).
waitpid system call • The second argument contains the exit status of the child. • The final argument options can take a variety of values defined in <sys/wait.h> • The most useful is the option WNOHANG • This allows waitpid to sit in a loop, without blocking. • waitpid returns the process id of the child process once terminated.
Zombies and premature exits • A process becomes a zombie when a child process exits before the parent process issues a wait. • This results in the process occupying space in the system’s process table but nothing else. • If a parent process exits before a child process is done. That process is “orphaned” and is “adopted” by the OS (and killed!).
The shell - What it shall do • Assemble commands and execute them • Execute in either foreground or background (command used with &). • Deal with a line with multiple commands separated by semicolons. • I/O redirection (< >) and pipe (|) will be added later (by you!)
A small Shell program • A shell is a command interpreter. • The idea is simple while( EOF not typed) { get command line from user assemble command args and execute wait for child }
The userin function • The userin.c will get the command line. • The program will print a prompt, then wait for a line of input from the keyboard. • Any input (read one character at a time) it receives will be placed in a buffer. • We shall set a max length for the command line, the program will also check for any violations.
The gettok.c program • This program extracts individual tokens from the command line constructed by userin. • A token is a lexical unit such as a command name or argument. • gettok is invoked as follows: • toktype = gettok(&tptr); • toktype is an integer indicating the type of token, defined in smallsh.h.
gettok.c continued • tptr is a character pointer that points to the actual token itself after the call to gettok. • Note that since it references the character pointers tok and ptr, it must be included in the same source file as userin. • This is why tok and ptr are initialized as they are in userin.
inarg is used to determine whether a character can be part of an ‘ordinary’ argument. For the time being, we need just check whether the character is special to smallsh or not:
Procline.c program • procline will parse a command line using gettok, constructing an argument list in the process. • When it encounters a newline or semicolon it invokes a routine called called runcommand to execute the command. • It assumes that an input has already been read with userin.
runcommand.c • The next stage is the runcommand function that actually starts any command processes. • The runcommand is very similar to the docommand seen earlier, except it takes an additional parameter (where) to indicate if the process is to be run in foreground or background. • The waitpid is also omitted (we’ll see why).