User Tools

Site Tools


os_cp:fork_exec_pipes:solutions

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

os_cp:fork_exec_pipes:solutions [2024/05/08 14:40] (current)
jkonczak utworzono
Line 1: Line 1:
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#include <​unistd.h>​
 +int main(void) {
 +  if (fork()) {
 +    write(1, "​parent\n",​ 7);
 +  } else {
 +    write(1, "​child\n",​ 6);
 +  }
 +  return 0;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#include <​unistd.h>​
 +int main(void) {
 +  if (fork()) {
 +    char c;
 +    read(0, &c, 1);
 +  }
 +  return 0;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#include <​stdio.h>​
 +#include <​unistd.h>​
 +int main(void) {
 +  execlp("​ps",​ "​ps",​ "​-F",​ NULL);
 +  perror("​execvp"​);​
 +  return -1;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +++++ The following version does a minimum of error checking. |
 +<code c>
 +#include <​errno.h>​
 +#include <​stdint.h>​
 +#include <​unistd.h>​
 +
 +int32_t doExpensiveComputation() { return 2 + 2; }
 +
 +int main() {
 +  int pfds[2];
 +  if (pipe(pfds) == -1) {
 +    perror("​pipe"​);​
 +    return 1;
 +  }
 +  int f = fork();
 +  if (f == -1) {
 +    perror("​fork"​);​
 +    return 1;
 +  }
 +  if (!f) {
 +    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;
 +}
 +</​code>​
 +++++
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +~~Exercise.#​~~
 +<code c>
 +#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;
 +}
 +</​code>​
 +
 +
 +~~META:
 +language = en
 +~~
  
os_cp/fork_exec_pipes/solutions.txt · Last modified: 2024/05/08 14:40 by jkonczak