This assignment is Due on: Day: Wednesday, April 29, 1998 Time: Before 6:00 PM WARNINGS: TURN IN THIS ASSIGNMENT ELECTRONICALLY USING "turnin". LATE ASSIGNMENTS WILL NOT BE ACCEPTED. ---------------------------------------------------------------------- The purpose of this homework is to reinforce explanation of the following C programming concepts: Use of fork(2) and exec(2) Use of getpid(2) and getppid(2) Use of wait(2) Use of nice(2) Use of getopt(3c) Accessing command line options Foreground/Background processing Note: DO NOT use waitpid()! Before beginning this homework, read pages 378-383 in the Weiss book. -----------------------Start Answer Here----------------------- [p0] 5.0 points Explain in some detail what UNIX command or commands you would use (and how you would use them) to (a) determine how many and what processes of yours are currently running, and (b) terminate them. ------------------------End Answer Here------------------------ The next problem will require you to create a new source program and then make several modifications to it. Please read the following steps through carefully to make sure you have a complete understanding of everything that needs to be done, BEFORE you begin. 0. Create a C source program called "myfork.c" that creates a child process. Use the following program fragment as a skeleton: #define FORK_ERR ( pid_t )-1 #define FORK_CHLD ( pid_t )0 int main( void ) { int i; pid_t Pid; if( ( Pid = fork( ) ) == FORK_ERR ) { /* * error stuff */ fprintf( stderr, "Can't create child\n" ); return EXIT_FAILURE; } else if( Pid == FORK_CHLD ) /* * child stuff */ printf( "Hello, world!\n" ); else /* * parent stuff */ printf( "Oh my gosh, it's alive!\n" ); return EXIT_SUCCESS; } 1. Modify the "myfork.c" file by adding one call to getpid(2) and one call to getppid(2) so that (instead of the original messages given above) the parent process prints this message: "My PID is ... , my child's PID is ..." and the child process prints this message: "My PID is ... , my parent's PID is ..." The ellipsis above should show the respective PIDs for each process. Getpid(2) and getppid(2) may not physically appear more than once each in the (post-preprocessor) program source. 2. Now modify the main() function of your "myfork.c" program so that (in addition to the previously mentioned messages) the parent process prints its PID message AFTER the child process prints its message. NOTE: Statement sequencing within the program does NOT guarantee order of execution. Synchronization of the parent's messages with respect to the child's messages must be GUARANTEED by the flow of control of your program. 3. Modify "myfork.c" so that the child process reduces its priority by 20 before printing any messages. 4. Now modify "myfork.c" so that the child process will exec() the "ps" command in such a way that the child's priority (which is reduced by 20 as a result of Step 3) is displayed by "ps". Only the info for that specific child process should be displayed by your call to "ps" - DO NOT DISPLAY INFO ABOUT ANY OTHER PROCESSES. You will have to look through the man pages for "ps" to find the correct options to pass to it. -----------------------Start Answer Here----------------------- [p1] 10.0 points Copy the source code for the final version of your main( ) function (from Step 2 above) here. ------------------------End Answer Here------------------------ Run the "myopt" program by typing each of the following commands in turn, and explain in some detail why the program produces the output that it does for each case (Note: a copy of the source code for "myopt" can be found in the ~cs2430/pub/src directory. For this problem, it is not necessary to make a copy of "myopt.c" in your own directory, but you will have to look at the original source code to figure out what is going on). -----------------------Start Answer Here----------------------- [p2] 15.0 points (a) myopt foo bar (b) myopt -o -r foo (c) myopt -n1000 foo (d) myopt -od foo bar (e) myopt -rn42foo -x ------------------------End Answer Here------------------------ The next problem will require you to create a new source program and then make several modifications to it. Please read the following steps through carefully to make sure you have a complete understanding of everything that needs to be done, BEFORE you begin. 0. Copy the "myopt.c" file from the ~cs2430/pub/src directory to a file called "myexec.c" in your own directory. Modify the main() function in your "myexec.c" file so that only -b and -f are recognized as valid options. Each of these two options must accept an additional arbitrary string (sub)option. Compile "myexec.c" and run it to be sure your arguments are being parsed correctly. 1. Add calls to fork() and some flavor of exec() such that the additional (sub)options passed with either -b or -f are run as children of your "myexec" program. Note: you will need a new variable of type "pid_t" to complete this part. NO OTHER NEW VARIABLES BESIDES THE pid_t MAY BE CREATED OR USED. 2. Verify correct operation of your program by typing each of the following commands in turn. You should see the output from each exec()-ed command, in order from left to right. myexec -b pwd myexec -f pwd -f date myexec -b pwd -f date -b whoami 3. Modify the "myexec.c" file, so that the additional (sub)options passed with -f will start a process that runs in "foreground" mode (i.e. the parent process waits for it to complete before continuing), and the additional (sub)options passed with -b will start a process that runs in "background" mode (i.e. the parent process does NOT wait for it to complete before continuing). The -b and -f options may appear in any order, and in any combination. Note that it is possible to have several processes running in the background, but that only ONE process at a time can run in the foreground. Your program must start all background processes in parallel, and then execute all foreground processes sequentially. DO NOT CREATE OR USE ANY NEW VARIABLES TO COMPLETE THIS PROBLEM. -----------------------Start Answer Here----------------------- [p3] 10.0 points Copy the modified source code for the main() function from your "myexec.c" file here ------------------------End Answer Here------------------------ Modify the main() function of your "myexec" program such that the following additional restrictions and requirements are satisfied. 0. Options specified with -b and -f must be parsed from left to right, using only a single pass with getopt(). Any argument specified with the -b option is immediately executed in the background. Arguments specified with the -f option are executed in the foreground, but only after the previously executed foreground process (if any) has finished. 1. The program also recognizes the -p option, which takes an arbitrary non-negative integer argument, which is interpreted as a priority "increment" in the style of nice(2). Multiple occurrences of -p may be specified, and will apply to all subsequent option arguments passed via -b or -f. If a negative number is passed as an argument, then the -p option is ignored (i.e. the current increment value does not change). For example: myexec -p 2 -f date -b pwd -p 4 -b whoami -f id would execute 'date' in the foreground and 'pwd' in the background, each with a priority increment of 2. Then it would execute 'whoami' in the background with an additional priority increment of 4, for a total increment of 6. After the 'date' that was running in the foreground finished, then 'id' would be run in the foreground with a priority increment of 6 (note that the effect of multiple priority increment options is additive - this is an effect of the way that nice(2) works). 3. New and/or temporary variables may be introduced as needed to accomplish steps 0-2 above. All other foreground/background requirements from Problem 3 above must still be met, however. -----------------------Start Answer Here----------------------- [p4] 10.0 points Copy the modified source code for the main() function from your "myexec.c" file here ------------------------End Answer Here------------------------