CMPS 3600 Lab-8 - Using Execve(2)

Goals

Overview of this lab... 1. You are given a program that runs and works. tvlab8.c The program uses semaphores. It works, but it doesn't cleanup the semaphores at the end. Your job is to cleanup the semaphores at the end. 2. To cleanup semaphores, you will run the program /usr/bin/ipcrm. The ipcrm program will be run using execve(2). Do it at the end of the program. Call execve with the correct parameters shown in the lab below. 3. If ./lab8 has a command-line argument of 1, then a. At the end of the program, fork a child process. b. Let the child process call execve to cleanup semaphores. The correct execve arguments are shown below. c. Make the parent process wait for the child to end. This must be done to avoid a zombie process. The point of the lab is to run the execve command in several different ways, and to avoid a zombie process.
resources

In tvlab8.c you will use the execve(2) system call, with and without fork(2). Start by reading material pertaining to execve in Ch 24 of TLPI (see link above) and the manpage for execve().

You may also refer to our phase1.c or phase2.c programs in which we have been working with the execve system call.

Copy the sample files into your directory:

     $ cp /home/fac/gordon/public_html/3600a/examples/8/sample1.c .
     $ cp /home/fac/gordon/public_html/3600a/examples/8/fork-exec.c .
     $ cp /home/fac/gordon/public_html/3600a/examples/8/nofork-exec.c . 
Compile and execute each program. Carefully study the code to understand what is happening in each program. Your job is to modify tvlab8.c to either fork() and execve() a command to remove the semaphore set or simply execve() the command. The choice depends on a flag entered on the command line. Get copy of tvlab8.c
      $ cp /home/fac/gordon/public_html/3600a/examples/8/tvlab8.c .

      to copy all lab files:
      $ cd
      $ cd 3600/8
      $ cp /home/fac/gordon/public_html/3600a/examples/8/* .

  Usage:
       ./lab8    /* means show a Usage statement            */
       ./lab8 0  /* means call execve without fork          */
       ./lab8 1  /* means fork a child that calls execve    */

  Your Makefile must build the lab8 executable by simply entering make.
  
BACKGROUND. Deciding to use fork() followed by execve() or an execve() without a fork depends on the circumstances. Without a fork execve() overlays the current process with the new process specified in the arguments to execve. The new process inherits the same PID, PPID, UID, etc. The old program is aborted. If you do not want to execute anything else in the original program then execve works for that.

If you call fork() and then call execve() in the child's code, the command passed in execve will take over the child. The parent process will continue running. When you call wait in the parent to grab the exit code you grab the code of the exec'd process.

The choice of fork or fork/exec depends on context - if you want to continue executing the current process then call fork & execve. If you do not wish to continue executing the current program, call execve. In this lab either choice will do the job - you will implement both. Which choice is taken depends on a flag passed in from the cmdline. If flag=0 then you do not call fork() before calling execve(). If flag=1 then you call fork() followed by execve().

The program has no code to remove semaphores.
You will add the execve to remove the semaphores.

A Linux command to remove semaphores is "/usr/bin/ipcrm" followed "-s" followed by the semaphore id.
When running ipcrm from execve(), you must pass a set of arguments that contain valuable information.
The code below demonstrates how to use sprintf to convert semid into a string, and to setup the arrays to pass as arguments to execve():

       char semid_str[20];
       /*sprintf(semid_str,"%d\0",semid);*/
       sprintf(semid_str,"%d%c", semid, '\0');
       char *newargv[] = { "/usr/bin/ipcrm", "-s", semid_str, NULL };
       char *newenv[] = { NULL };

       The arrays above are used as arguments for execve.
The last NULL argument terminates your argv array with a NULL pointer (see sample1.c). If you forget the NULL pointer your code will not work.
      An argument list is an array of character strings.
      same as an array of pointers.
      same as an array of addresses.
      The array null terminator acts as a sentinel to mark the end of the list.
      It is a null address, of type char, and should be defined like this:
      (char *)0
      An address value of zero type-casted to the array type.
  

If your ./lab8 received a command-line argument of 1, then you forked a child.
In this case, call wait() from the parent.
Display the child's exit code.
The exit code will be set by the ipcrm() process.
If you do not do this you will get a zombie!

Sample runs:

No argument
gordon@odin:~/3600/8$ ./lab8 Usage: ./lab8 <flag> Examples: ./lab8 means show this Usage statement ./lab8 0 means call execve without fork ./lab8 1 means fork a child that calls execve
flag = 0
gordon@odin:~/3600/8$ ./lab8 0 Lab-8 is running... created 4 created 3 created 2 created 1 created 0 [0][1][2]joined tv1 [3]joined tv2 joined tv3 [4]joined tv4 joined tv5 Added code to cleanup semaphores. Executing ipcrm.
flag = 1
gordon@odin:~/3600/8$ ./lab8 1 Lab-8 is running... created 4 created 3 created 2 created 1 created 0 [0][1][2]joined tv1 joined tv2 joined tv3 [3][4]joined tv4 joined tv5 Added code to cleanup semaphores with a fork. Executing ipcrm. icprm exited with status: 0
using strace
$ strace -q -f -e trace=execve ./lab8 1 2>out Lab-8 is running... created 4 created 3 created 2 created 1 created 0 [0][1]joined tv1 [2]joined tv2 [3]joined tv3 [4]joined tv4 joined tv5 Added code to cleanup semaphores with a fork. Executing ipcrm. icprm exited with status: 0 $ cat out execve("./lab8", ["./lab8", "1"], 0x7ffc978ba988 /* 32 vars */) = 0 [pid 1726] +++ exited with 0 +++ [pid 1725] +++ exited with 0 +++ [pid 1724] +++ exited with 0 +++ [pid 1723] +++ exited with 0 +++ [pid 1722] +++ exited with 0 +++ [pid 1727] execve("/usr/bin/ipcrm", ["/usr/bin/ipcrm", "-s", "82018309"], 0x7ffc8a70ba88 /* 0 vars */) = 0 [pid 1727] +++ exited with 0 +++ --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=1727, si_uid=10042, si_status=0, si_utime=0, si_stime=0} --- +++ exited with 0 +++

files to be collected from Odin...

     3600/8/tvlab8.c 
     3600/8/Makefile
     3600/8/foo        <---required