Computer Systems
Creating and Executing Unix Processes

Introduction

Fundamental to all operating systems is the concept of a process. While somewhat abstract, a process consists of an executing (running) program, its current values, state information, and the resources used by the operating system to manage the execution of the process. A process is a dynamic entity. In most operating systems, at any given point in time, multiple processes appear to be executing concurrently.

With the exception of some initial processes, all processes in UNIX are created by the fork system call. In fact, the Unix shell is constantly forking processes.

The exec family of system calls provides a facility for overlaying the calling process with a new executable module. It is often used in conjunction with fork, with the child execing the desired program, and the parent continuing to execute the original code.

The wait system call lets a parent process wait for a child to finish. It will cause the caller to pause until a child terminates. It will return immediately if the process has no children, or a child has terminated previously but not yet been waited for.

The following five activities will give you some practical experience with creating and executing processes in Unix using the following system calls:

	fork, wait, exit
	execv, execl 

Activity 1

Write a program pfork.c that does the following: Have your program print a message in case the command line is invalid:
	if(argc < 3)
     	{
    		printf("Invalid command line: please supply two integer values\n");
        	exit(1);
      	}
Hint: Use the atoi function to covert strings to their integer value.

Here is a sample output for this activity (assuming command line pfork 12 16):

 	[Child  1235]: Difference of 12 and 16 is -4.
 	[Parent 1234]: Sum of 12 and 16 is 28.
or
 	[Parent 1234]: Sum of 12 and 16 is 28.
 	[Child  1235]: Difference of 12 and 16 is -4.    

Activity 2

In this activity we will make use of execv to run other executable modules:
  1. At the shell prompt, try the command
        ps -f
    
    A list of your own processes currently running will be displayed:

    Very likely, your only process currently running is the bash shell. For a list all processes in the system, try

        ps -e -f
    
    Optionally, for more information on ps, use the Unix manual pages (type in man ps at the shell prompt).

  2. Find out the full path for the command ps by typing in at the shell prompt
        which ps
    
    You will likely find out that the full path for ps is /bin/ps.

  3. Copy the program from Activity 1 into a new file pexec.c. Extend the code for the child to do the following:

    Here is a sample output (assumming the command line pexec 12 16):

    	[Parent 1234]: Sum of 12 and 16 is 28.
    	[Child  1235]: Difference of 12 and 16 is -4.
    
         	UID     PID   PPID   C    STIME TTY      TIME CMD
         	mdamian 22686 22684  0 14:12:26 pts/5    0:01 -bin/bash
         	mdamian 22826 22686  0 15:11:49 pts/5    0:00 pexec
         	mdamian 22827 22826  0 15:11:49 pts/5    0:00 ps
    
    Make sure the parent waits for the child to finish executing.

  4. Is it possible to have the child execute ps -e -f first, and then print out the difference value? Explain your answer.

Activity 3

In this activity we will experiment with other variants of execv.

Activity 4

The word count program wc can take its input from a file whose name is specified in the command line. For instance, the Unix command
    wc filename
will print out the number of lines in the file with name filename. Write a small program linecount.c that takes any number of file names as command line parameters. For each filename in the command line, the program should create a child process that does the following:
  1. Prints out the name of the file
  2. Uses execl to execute the program wc on that file
The parent process should not exit until all processes have exited.

Here is a sample output (user input is in italics, aa and bb are two files in the same directory as xlinecount):

    bash$ ./xlinecount aa bb
    aa
           3       2       9   aa
    bb
           5       6      41   bb
For each file, the first column lists the total number of lines, the second column lists the total number of words and the third column lists the total number of characters.

Activity 5

Write your own mysystem function that behaves like the standard C library system function. Your function should have the following prototype:
    void mysystem(char * cmd);
Your function should not call the library system function. You will need to implement the following steps:
  1. Tokenize the command argument cmd and save each token in an array of strings
  2. The main process invokes fork to create a child process, then waits for the child to finish executing
  3. The child process invokes execv with arguments taken from the array of strings
Write a test program for your mysystem function. For example, the call
    mysystem("wc aa");
should produce the output
	      3       2       9   aa
Here aa is the same file used in Activity 4, and must exist in the same directory as your executable.