User Tools

Site Tools


Sidebar

os_cp:fork_exec_pipes:solutions

Exercise 1

#include <unistd.h>
int main(void) {
  sleep(5);
  write(1, "about to fork...\n", 17);
  fork();
  write(1, "forked.\n", 8);
  sleep(5);
  return 0;
}

Exercise 2

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
  pid_t f = fork();
  printf("fork: %-10dpid: %-10dppid: %-10d\n", f, getpid(), getppid());
  return 0;
}

Exercise 3

#include <unistd.h>
int main(void) {
  if (fork()) {
    write(1, "parent\n", 7);
  } else {
    write(1, "child\n", 6);
  }
  return 0;
}

Exercise 4

#include <unistd.h>
int main(void) {
  if (fork()) {
    char c;
    read(0, &c, 1);
  }
  return 0;
}

Exercise 5

#include <stdio.h>
#include <unistd.h>
int main(void) {
  execlp("ps", "ps", "-F", NULL);
  perror("execvp");
  return -1;
}

Exercise 6

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
  char **av = malloc(sizeof(char *) * (argc + 4));
  char a0[] = "ls";    av[0] = a0;
  char a1[] = "-l";    av[1] = a1;
  char a2[] = "-t";    av[2] = a2;
  char a3[] = "-r";    av[3] = a3;
  for (int i = 0; i < argc; ++i)
    av[i + 4] = argv[i + 1];
  execvp("ls", av);
  perror("execvp");
  return -1;
}

Exercise 7

#include <stdio.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
 
int main(int argc, char *argv[]) {
  struct timespec start, end;
  timespec_get(&start, TIME_UTC);
  if (!fork()) {
    execvp(argv[1], argv + 1);
    perror("execvp");
    return -1;
  }
  wait(NULL);
  timespec_get(&end, TIME_UTC);
  double elapsedSec = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
  printf("%f\n", elapsedSec);
  return 0;
}

Exercise 8

#include <assert.h>
#include <stdio.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>
 
int main(int argc, char *argv[]) {
  struct timespec start, end;
  timespec_get(&start, TIME_UTC);
  if (!fork()) {
    execvp(argv[1], argv + 1);
    perror("execvp");
    return -1;
  }
  close(0);
  close(1);
  int status;
  wait(&status);
  timespec_get(&end, TIME_UTC);
  double elapsedSec = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
  if (WIFEXITED(status)) {
    // You may test exit status by compiling & using the following program:
    // main(int,char**v){return atoi(v[1]);}
    fprintf(stderr, "%f (returned %d)\n", elapsedSec, WEXITSTATUS(status));
  } else {
    assert(WIFSIGNALED(status));
    fprintf(stderr, "%f (killed by signal %d)\n", elapsedSec, WTERMSIG(status));
  }
  return 0;
}

Exercise 9

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
 
int main() {
  int fd = open("output", O_WRONLY | O_TRUNC | O_CREAT, 0666);
  if (fd == -1) {
    perror("output");
    return 1;
  }
  dup2(fd, 1);
  close(fd);
  execlp("ps", "ps", "-F", NULL);
  return 1;
}

Exercise 10

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
 
int main(int argc, char **argv) {
  if (argc < 2) {
    write(2, "Too few arguments\n", 18);
    return 1;
  }
  int fd = open(argv[1], O_RDONLY);
  if (fd == -1) {
    perror(argv[1]);
    return 1;
  }
  dup2(fd, 0);
  close(fd);
  argv[1] = "tr";
  execvp("tr", argv + 1);
  return 1;
}

Exercise 11

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
 
int main() {
  int fileFd = open("file", O_WRONLY | O_CREAT | O_TRUNC, 0666);
  if (fileFd == -1) {
    perror("file");
    return 1;
  }
  int errorFd = dup(2);
 
  errno = ELOOP;
  perror("ELOOP");
  dup2(fileFd, 2);
  perror("ELOOP");
 
  errno = EMFILE;
  dup2(errorFd, 2);
  perror("EMFILE");
  dup2(fileFd, 2);
  perror("EMFILE");
 
  close(errorFd);
  close(fileFd);
  return 1;
}

Exercise 12

#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
 
int32_t doExpensiveComputation() { return 2 + 2; }
 
int main() {
  int pfds[2];
  pipe(pfds);
  if (!fork()) {
    int32_t result = doExpensiveComputation();
    write(pfds[1], &result, 4);
    return 0;
  }
  int32_t result;
  read(pfds[0], &result, 4);
  printf("The result is: %d\n", result);
  return 0;
}

The following version does a minimum of error checking.

Exercise 13

#include <stdint.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
 
int32_t doExpensiveComputation() {
  sleep(3);
  return 2 + 2;
}
 
int main() {
  int pfds[2];
  pipe(pfds);
  for (int i = 0; i < 3; ++i) {
    if (!fork()) {
      int32_t result = doExpensiveComputation();
      write(pfds[1], &result, 4);
      return 0;
    }
  }
 
  int32_t result[4];
  result[3] = doExpensiveComputation();
 
  for (int i = 0; i < 3; ++i) {
    read(pfds[0], result + i, 4);
    wait(NULL);
  }
 
  printf("The result is: %d\n", result[0] + result[1] + result[2] + result[3]);
  return 0;
}

Exercise 14

#include <ctype.h>
#include <stdio.h>
#include <unistd.h>
 
int main() {
  int pfds[2];
  pipe(pfds);
  if (!fork()) {
    dup2(pfds[1], 1);
    close(pfds[0]);
    close(pfds[1]);
    execlp("ls", "ls", "-l", NULL);
    return 1;
  }
  close(pfds[1]);
  char c;
  while (1 == read(pfds[0], &c, 1)) {
    c = toupper(c);
    write(1, &c, 1);
  }
  return 0;
}

Exercise 15

#include <unistd.h>
 
int main() {
  int pfds[2];
  pipe(pfds);
  if (!fork()) {
    dup2(pfds[1], 1);
    close(pfds[0]);
    close(pfds[1]);
    execlp("ps", "ps", "-eF", NULL);
    return 1;
  }
  dup2(pfds[0], 0);
  close(pfds[0]);
  close(pfds[1]);
  execlp("sort", "sort", "-nk6", NULL);
  return 1;
}
os_cp/fork_exec_pipes/solutions.txt · Last modified: 2024/05/08 14:40 by jkonczak