COMP309/509 - Parallel and Distributed Computing

Lecture 3 - Process Control

By Mitchell Welch

University of New England


Reading


Summary


Final points on fork()


Final points on fork()

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int     globvar = 6;        /* external variable in initialized data */

int main(void)s{
    int     var;        /* automatic variable on the stack */
    pid_t   pid;

    var = 88;
    printf("before vfork\n");   /* we don't flush stdio */
    if ((pid = vfork()) < 0) {
        perror("vfork error");
    } else if (pid == 0) {      /* child */
        globvar++;              /* modify parent's variables */
        var++;
        _exit(0);               /* child terminates */
    }

    /* parent continues here */
    printf("pid = %ld, glob = %d, var = %d\n", (long)getpid(), globvar,
      var);
    exit(0);
}

Final points on fork()


Final points on fork()


Final points on fork()


Process Termination


Process Termination


Process Termination

.center[default-aligned image]


Process Termination

#include <stdlib.h>

int atexit( void (*func)(void));

//Returns 0 of the function is called correctly and nonzero on error

Process Termination

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

static void my_exit1(void);
static void my_exit2(void);

int main(void){
    if (atexit(my_exit2) != 0)
        perror("can't register my_exit2");
    if (atexit(my_exit1) != 0)
        perror("can't register my_exit1");
    if (atexit(my_exit1) != 0)
        perror("can't register my_exit1");
    printf("main is done\n");
    return(0);
}

static void my_exit1(void){
    printf("first exit handler\n");
}

static void my_exit2(void){
    printf("second exit handler\n");
}

Process Termination


Process Control Using wait()


Process Control Using wait()


#include <sys/wait.h>

pid_t wait(int *staloc);

pid_t waitpid(pid_t pid, int *statloc, int options);

Process Control Using wait()


Process Control Using wait()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void){ 
  int i, n = 4, status;
  pid_t childpid;
  for (i = 1; i < n;  ++i)
    if((childpid = fork()) < 0){ 
      /* fork error */
      perror("error in fork"); 
      exit(EXIT_FAILURE); }  
    else if(childpid){ 
      /* parent code */ 
      wait(&status);
      break;
    } else { 
      /* child code  */ 
    }
  /* mutual code */
  printf("This is process %d with parent %d\n",
         getpid(), getppid());
  return 0;
}

Process Control Using wait()


Process Control Using wait()

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void){
    pid_t   pid;
    if ((pid = fork()) < 0) {
        perror("fork error");
    } else if (pid == 0) {      /* first child */
        if ((pid = fork()) < 0)
            perror("fork error");
        else if (pid > 0)
            exit(0);    /* parent from second fork == first child */

        /* We're the second child; our parent becomes init as soon
        *  as our real parent calls exit() in the statement above.
        *  Here's where we'd continue executing, knowing that when
        *  we're done, init will reap our status.*/

        sleep(2);
        printf("second child, parent pid = %ld\n", (long)getppid());
        exit(0);
    }
    if (waitpid(pid, NULL, 0) != pid)   /* wait for first child */
        perror("waitpid error");
    exit(0);
}

Process Control Using wait()


Process Control Using wait()

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>

int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);

pid_t wait3(int *statloc, int options, struct rusage *rusage);

pid_t wait3(pid_t pid, int *statloc, int options, struct rusage *rusage);

Process Control Using wait()


Executing New Programs with exec()

#include <unistd.h>

extern char **environ;
int execl(const char *path, const char *arg0, ... /*, (char *)0 */);
int execv(const char *path, char *const argv[]);
int execle(const char *path, const char *arg0, ... /*,
       (char *)0, char *const envp[]*/);
int execve(const char *path, char *const argv[], char *const envp[]);
int execlp(const char *file, const char *arg0, ... /*, (char *)0 */);
int execvp(const char *file, char *const argv[]);
int fexecve(int fd, char *const argv[], char *const envp[])

Executing New Programs with exec()


Executing New Programs with exec()


Executing New Programs with exec()


#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
  pid_t childpid, waitreturn;
  int status;
  if ((childpid = fork()) == -1) {
    perror("The fork failed");
    exit(1);
  } else if (childpid == 0) {
    /* child code */
    if (execvp(argv[1], &argv[1]) < 0) {
      perror("The exec of command failed");
      exit(1);
    }
    ...

Executing New Programs with exec()

  ...

  } else
    /* parent code */
    while(childpid != (waitreturn = wait(&status)))
      if ((waitreturn == -1) && (errno != EINTR))
        break;
  exit(0);
}

Executing New Programs with exec()

#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include "makeargv.h"
int main(int argc, char *argv[]){
  char **myargv, delim[] = " \t";
  pid_t childpid, waitreturn;
  int status;
  if (argc != 2) {
    fprintf(stderr, "Usage: %s string\n", argv[0]);
    exit(EXIT_FAILURE);
  }
  if ((childpid = fork()) == -1) {
    perror("The fork failed");
    exit(EXIT_FAILURE);
  } else if (childpid == 0) {
    /* child code */
    if (makeargv(argv[1], delim, &myargv) < 0) {
      fprintf(stderr, "Argument array could not be constructed\n");
      exit(EXIT_FAILURE);
    } else if (execvp(myargv[0], &myargv[0]) < 0) {
      perror("The exec of command failed");
      exit(EXIT_FAILURE);
    } 
    ...

Executing New Programs with exec()

   ...

  } else
    /* parent code */
    while(childpid != (waitreturn = wait(&status)))
      if ((waitreturn == -1) && (errno != EINTR))
        break;
  exit(EXIT_SUCCESS);
}

Files and File Descriptors


Files and File Descriptors


Files and File Descriptor

.center[default-aligned image]


Files and File Descriptor


Summary


class: middle, center, inverse

Questions?


Reading


Next Lecture