Fork and pipe

Class: CSCE-313


Notes:

Question 1

What is returned by fork() in the child process?

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#Forks


Fork & exec

Evaluate whether the following statements regarding fork and exec are true or false


Question 2

After a fork(), the parent receives the PID of the child process as the return value.

Options:

Overall explanation:

Tags: Lab 2 - Unix Pipes

Question 3

After a fork(), the child receives its own PID as the return value.

Options:

Overall explanation:

Tags: Lab 2 - Unix Pipes

Question 4

After a fork(), the parent and child processes are nearly identical.

Options:

Overall explanation:

Tags: Lab 2 - Unix Pipes

Question 5

During a fork(), the parent process is terminated if an error occurs.

Options:

Overall explanation:

Tags: Lab 2 - Unix Pipes

Question 6

After a fork(), the parent process is guaranteed to run first.

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#Forks

Question 7

After a fork(), the child process is guaranteed to run first.

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#Forks

Question 8

After a fork(), the next process to run is determined by the scheduler.

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#Forks

Question 9

After an exec(), a new process is created.

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What is exec()?]]

Question 10

After an exec(), new program code is loaded into the process.

Options:

Overall explanation:

Tags: [[03 - Inter Process Communication - Pipes and FIFO#An aside-execl]]

Question 11

You must always call fork() before you call exec().

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What is exec()?]]

Question 12

You must always call exec() after you call fork().

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What is exec()?]]

Question 13

When a parent process exits, all child processes must immediately exit.

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What happens in exec()]]

Question 14

If exec() succeeds, it returns to the calling program.

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What happens in exec()]]

Question 15

A child process created by fork() initially has the same program code as its parent.

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#Forks

Question 16

Calling wait() or waitpid() allows a parent to wait for a child process to terminate.

Options:

Overall explanation:

Tags: 04 - Process API - Part I#Example command interpreter (solved)

Question 17

In UNIX, where is the buffer used to implement a pipe (as in the pipe system call) located?

Options:

Overall explanation:

Tags: 03 - Inter Process Communication - Pipes and FIFO#What is a pipe in Linux?

Question 18

Immediately after fork() completes, if a parent process and its child process read from the same virtual address, which of the following is true? Read about the Copy-on-write (COW) optimization that the Unix kernel uses with fork() to avoid copying a process’s entire memory unless it’s actually needed.

Options:

Overall explanation:

Question 19

After a successful exec() call, which of the following remains unchanged?

Options:

Overall explanation:

Tags: [[04 - Process API - Part I#What happens in exec()]]

Question 20

Which of the following best describes the relationship between a parent and child process immediately after fork()?

Options:

Overall explanation:

Tags: [[03 - Inter Process Communication - Pipes and FIFO#UNIX fork()]]


Consider the two programs shown below.

// Program 1
#include <cstdio>
#include <unistd.h>

int main() {
    printf("PID %d running prog1\n", getpid());
    return 0;
}

// Program 2
#include <cstdio>
#include <unistd.h>
#include <sys/wait.h>

int main() {
    char *argv[2];
    argv[0] = (char *)"prog1";
    argv[1] = nullptr;

    printf("PID %d running prog2 (parent before fork)\n", getpid());

    pid_t pid = fork();

    if (pid == 0) {  
        // Child process  
        execv("./prog1", argv);  
  
        // Only runs if execv fails  
        perror("execv failed");
        return 1;
    } else {  
        // Parent process  
        waitpid(pid, nullptr, 0);
        printf("PID %d exiting from prog2 (parent after wait)\n", getpid());
    }

    return 0;
}

Question 21

How many different PIDs will print out if you run Program 2?

Output:

macc@craftlab:~/TAMUcode/CSCE-313$ ./prog2
PID 2897235 running prog2 (parent before fork)
PID 2897236 running prog1
PID 2897235 exiting from prog2 (parent after wait)

Answer: 2

Question 22

How many lines of output will you see (assuming execv("./prog1", argv) succeeds)?

Output:

PID 2897235 running prog2 (parent before fork)
PID 2897236 running prog1
PID 2897235 exiting from prog2 (parent after wait)

Answer: 3

Question 23

What are the lines of output? When outputting a line, use xxx to denote an unknown PID.

Output (with PIDs unknown):

PID xxx running prog2 (parent before fork)
PID xxx running prog1
PID xxx exiting from prog2 (parent after wait)

Question 24

Which process prints the line PID ... running prog1 ?

Options:

Overall explanation:

Tags: Lab 2 - Unix Pipes#2. Create child to run first command

Question 25

In Program 2, how many times does fork() return?

Answer: 2

Overall explanation:


Creating a pipeline

Do Problem 1 on the class website. When indicating the sequence of statements corresponding to [A], [B] etc., make sure that your response has no whitespace and that a sequence of statements is separated by a comma. For e.g., if [A] should be replaced by the sequence 3, 4, & 7 in that order then indicate it as 3,4,7.

Problem 1. Here’s the skeleton of a shell function implementing a simple two-command pipeline, such as “cmd1 | cmd2”.

void simple_pipe(char* cmd1, char** argv1, char* cmd2, char** argv2) {
    int pipefd[2], r, status;

    [A]

    pid_t child1 = fork();
    if (child1 == 0) {
        [B]
        execvp(cmd1, argv1);
    }
    assert(child1 > 0);

    [C]

    pid_t child2 = fork();
    if (child2 == 0) {
        [D]
        execvp(cmd2, argv2);
    }
    assert(child2 > 0);

    [E]
}

And here is a grab bag of system calls. STDIN_FILENO is a macro that expands to 0, and STDOUT_FILENO expands to 1.

  1. close(pipefd[0]);
  2. close(pipefd[1]);
  3. dup2(pipefd[0], STDIN_FILENO);
  4. dup2(pipefd[0], STDOUT_FILENO);
  5. dup2(pipefd[1], STDIN_FILENO);
  6. dup2(pipefd[1], STDOUT_FILENO);
  7. pipe(pipefd);
  8. r = waitpid(child1, &status, 0);
  9. r = waitpid(child2, &status, 0);

Your task is to assign system call IDs, indicated by numerals such as “1”, to slots, such as “A”, to achieve a correct foreground pipeline. You can assume that execvp(cmd, argv) is a version of exec that replaces the caller process with the execution of cmd run with arguments in argv.


Question 26

Which system call(s) should be placed at location [A] to correctly initialize the pipeline?

Answer:

7

Overall explanation:

Question 27

Which system call(s) should be placed at location [B] so that cmd1 writes its output to the pipe?

Answer:

6,1

Overall explanation:

Question 28

Which system call(s) should be placed at location [D] so that cmd2 reads its input from the pipe?

Answer:

3,2

Overall explanation:

Question 29

When a parent process exits, what happens to its child processes?

Options:

Overall explanation:

Tags: 04 - Process API - Part I

Question 30

For each of the actions below, select the most appropriate system call from the following list.

Options:

Answer:

  1. Obtain the termination status of a child process.: wait
  2. End the execution of the current process.: exit
  3. Deliver a signal to another process.: kill
  4. Load and execute a different program within the current process.: exec
  5. Create a child process.: fork

Overall explanation: