> HW2 > released: 01/26,15:00 > due: 02/01, 23:59 > > Answer the following questions. > Submit your answers to Canvas assignments. > There is an entry for this homework. > > > 1. fork, short circuit, and adoption (6 points) > > Read the C code below and answer the questions. > > #include > #include > #include > > int main(){ > printf("[%d]: main process\n", getpid()); > fork() || fork(); > printf("[%d]: my parent is %d\n", getpid(), getppid()); > } > > Questions: > > 1.a (1 point) > Run the C code above and what outputs do you get (copy them below)? > [23899]: main process [23899]: my parent is 48083 [23901]: my parent is 1 [23902]: my parent is 23901 > > 1.b (2 points) > Why does the program have such outputs? > Explain why in 2--3 sentences. > [hints: > - pay attention to the return values of "fork()" > - study "||" operator in C > - what you saw is called "short circuit" > ] > The main process (pid=23899) calls fork(), and creates a child process (pid=23901). Because of the "short circuit", the parent skips the second fork(), and the child runs fork() and gives birth to a third process (pid=23902). Three processes call the printf in the end. > > [update 01/30: the 1.c and 1.c below (one is a typo; should have been "1.d") > are ambiguous in multiple ways. So, we rephrase the questions to be a new 1.c. > You can submit answers to either the new "1.c" or the old two "1.c"s. > Both are valid answers.] > > // 1.c (1 point) > // You should see multiple lines of "[ABC]: my parent is [XYZ]", > // where "[ABC]" and "[XYZ]" are integers (in fact, process ids). > // There is one "[XYZ]" (namely parent pid) that hasn't shown up in any line of > // "[ABC]" (the process who prints this line). > // Who is this "[XYZ]"? > // [hint: use "echo $$" to show the pid of the shell] > // > // > // 1.c (1 point) > // Are there processes whose parent is pid=1? (if no, say "no") > // If yes, why its parent is pid=1? can you give a guess in 1 sentence? > // [hint keyword: orphan process] > > 1.c (2 points) [update 01/30: this is a new 1.c] > You should see multiple lines of "[ABC]: my parent is [XYZ]", > where "[ABC]" and "[XYZ]" are integers (in fact, process ids). > There are two "[XYZ]" (namely parent pid) that haven't shown up in any line of > "[ABC]" (the process who prints this line). > Who are the two "[XYZ]"? > [hints: > -- use "echo $$" to show the pid of the shell > -- hint keyword: orphan process > ] > In my case, unseen "[XYZ]" are 48083 and 1. * pid=48083 is the pid of my shell process. * pid=1 is the init process on my machine, which adopts orphan processes. > > > 1.d (1 point) > [update 01/30: if you haven't seen pid=1, then say "not apply"] > To avoid getting pid=1, Ryan modified the program to be: > > int main(){ > printf("[%d]: main process\n", getpid()); > fork()|| fork(); > printf("[%d]: my parent is %d\n", getpid(), getppid()); > > wait(NULL); > } > > Will this work? > Explain why in 1 sentence. > Yes. Because wait() will make the parent wait to avoid orphan processes. > > > > 2. Pipe, a potential pitfall in Lab2 (4 points) > > Read the following code about syscall pipe and answer questions: > > #include > #include > #include > #include > #include > #include > > int > main(int argc, char *argv[]) > { > int pipefd[2]; > pid_t pid; > char buf; > > if (argc != 2) { > fprintf(stderr, "Usage: %s \n", argv[0]); > exit(EXIT_FAILURE); > } > > if (pipe(pipefd) == -1) { > perror("pipe"); > exit(EXIT_FAILURE); > } > > pid = fork(); > if (pid == -1) { > perror("fork"); > exit(EXIT_FAILURE); > } > > if (pid == 0) { // child > close(pipefd[1]); // <---HERE > > while (read(pipefd[0], &buf, 1) > 0) > write(STDOUT_FILENO, &buf, 1); > > write(STDOUT_FILENO, "\n", 1); > close(pipefd[0]); > exit(EXIT_SUCCESS); > > } else { // parent > close(pipefd[0]); // Close unused read end > write(pipefd[1], argv[1], strlen(argv[1])); > close(pipefd[1]); // Reader will see EOF > wait(NULL); // Wait for child > exit(EXIT_SUCCESS); > } > } > > > Questions: > > 2.a (1 point) > What does this program do? > Explain in 1--2 sentences. > This program forks two processes, connect the via a pipe, send the user-typed argument from one to the other, and print the argument. > > 2.b (1 point) > If you comment out the line with "<---HERE", what has changed when you > compile and rerun the program? > [hint: notice if the program finishes.] > The program never exits. > > 2.c (2 points) > Why does commenting the line with "<---HERE" have this consequence? > Explain why in 1--2 sentences. > [hint: this is THE most frequent bug in Lab2. > You do want to understand why and avoid it.] > For the line "while (read(pipefd[0], &buf, 1) > 0)", the process can quit only when the **all** write-end of the pipe are closed. If commenting out the line with close(), there always exists an opened write-end, so the process will keep waiting for inputs.