XXXXXXXXXXlabs/lab5.md at master · ITF22519/labs
https:
github.com/ITF22519/labs
lo
maste
lab5/lab5.md 1/8
ITF22519 / labs Private
Code Issues Pull requests Actions Projects Security Insights
labs / lab5 / lab5.md
anlam Update lab5.md Latest commit 428f5cf 13 days ago History
1 contributo
Learn Git and GitHub without any code!
Using the Hello World guide, you’ll start a
anch, write comments, and open a pull request.
Read the guide
master Go to file
298 lines (234 sloc XXXXXXXXXXKB
ITF XXXXXXXXXXIntroduction to Operating Systems
Autumn 2020
Lab 5: Introduction to Unix Processes
Before you start, remember to commit and push your previous lab to your git repository. Then, try to pull the new lab:
$ cd ITF22519/labs
$ git pull upstream master
$ git pull origin master
$ cd lab5
Please remember these steps for the future labs.
Raw Blame
https:
github.com/ITF22519
https:
github.com/ITF22519/labs
https:
github.com/ITF22519/labs
https:
github.com/ITF22519/labs/issues
https:
github.com/ITF22519/labs/pulls
https:
github.com/ITF22519/labs/actions
https:
github.com/ITF22519/labs/projects
https:
github.com/ITF22519/labs/security
https:
github.com/ITF22519/labs/network/dependencies
https:
github.com/ITF22519/labs
https:
github.com/ITF22519/labs/tree/maste
lab5
https:
github.com/anlam
https:
github.com/anlam
https:
github.com/ITF22519/labs/commit/428f5cfa19c8ce3f50025c0e13408b76c5fa1230
https:
github.com/ITF22519/labs/commit/428f5cfa19c8ce3f50025c0e13408b76c5fa1230
https:
github.com/ITF22519/labs/commits/maste
lab5/lab5.md
https:
guides.github.com/activities/hello-world
https:
github.com/ITF22519/labs/find/maste
https:
github.com/ITF22519/labs
aw/maste
lab5/lab5.md
https:
github.com/ITF22519/labs
lame/maste
lab5/lab5.md
x-github-client:
openRepo/https:
github.com/ITF22519/labs?
anch=master&filepath=lab5%2Flab5.md
https:
github.com/login?return_to=%2FITF22519%2Flabs%2Fblob%2Fmaster%2Flab5%2Flab5.md
https:
github.com/login?return_to=%2FITF22519%2Flabs%2Fblob%2Fmaster%2Flab5%2Flab5.md
XXXXXXXXXXlabs/lab5.md at master · ITF22519/labs
https:
github.com/ITF22519/labs
lo
maste
lab5/lab5.md 2/8
I wrote this lab using Markdown ( .md ) which is a very simple markup language for documentation. You can find an example of
markdown here. I was thinking maybe you should also try using markdown to write your reports (or enter your answers of the la
exercises directly into this file). This is not mandatory, just a suggestion. I just wanted to introduce to you a very cool language that
developers use to document their code.
About Unix Processes
1. When a system is booted, the first user space process is systemd (or /sbin/init depending on your Linux Distribution), and has a
PID of 1. This process will in turn launch startup scripts and eventually login prompts. If you do a ps -el , you should see that process
1 is systemd . It will be the ancestor of all other user processes on the system.
2. When you login or start a terminal, a process for the shell is started. The shell will then launch other processes, which will be children
of the shell. If the parent process dies (for example, you exit the shell), systemd will adopt the orphaned processes (on Linux and
many other Unix variants).
3. The status of a Unix process is shown as the second column of the process table (viewed by executing the ps command). Some of
the states are R: running, S: sleeping, Z: zombie.
Process Table
The program print_pid.c prints out its process id as well as its parent’s id, and then sleeps for 2 minutes. Run the program print_pid.c
twice, both times as a background process (i.e. suffix it with an ampersand “ & ”):
$ ./print_pid &
Ctrl+C
$ ./print_pid &
Ctrl+C
Pay attention to the id of the parent processes printed by this program. Once both processes are running as background processes, view
the process table (use ps -l to view only the processes running on your terminal, or ps -el to view all processes on the system). If you
see the message “I am awake”, the process has finished and will no longer show up in the process table. The first line from a ps -l is
duplicated here:
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
A short description of the fields could be found here: https:
docs.oracle.com/cd/E XXXXXXXXXX/ XXXXXXXXXX/spprocess-47/index.html. You
should be able to find more details of these fields in the ps manual page ( man ps ).
Exercise 1 (10 pts)
(8 pts) In the report, include only relevant lines from ps -l for your programs, and point out the following items:
process name (Process CMD)
process state (decode the letter!)
process ID (PID)
parent process ID (PPID)
(2 pts) Find out the name of the process that started your print_pid programs. What is it, and what does it do?
https:
github.com/ITF22519/demo-markdown
https:
docs.oracle.com/cd/E XXXXXXXXXX/ XXXXXXXXXX/spprocess-47/index.html
XXXXXXXXXXlabs/lab5.md at master · ITF22519/labs
https:
github.com/ITF22519/labs
lo
maste
lab5/lab5.md 3/8
Kill processes
Now that you know how to find a PID for a running program, you can use kill to terminate an unwanted process. Just type kill
followed by the process ID. If a process refuses to terminate, kill -9 followed by the process ID will terminate any process you have
permission to kill. You might also try killall to kill all processes with the same name (try man killall for more information).
$ killall print_pid
The fork() system call
The fork() call creates a child that is a copy of the parent process. Because the child is a copy, both it and its parent process begin from
just after the fork() . All of the statements after a call to fork() are executed by both the parent and child processes. However, both
processes are now separate and changes in one do not affect the other.
The code fragment below calls fork() once, which results in the creation of one child process. Then, each process prints out its id and the
parent’s id.
int main() {
fork();
printf("Process %d's parent process ID is %d\n", getpid(), getppid());
return 0;
}
The output of this program could be:
Process 14427's parent process ID is 6891
Process 14428's parent process ID is 14427
Here, the id of the main function is 14427, the child id is 14428, and the id of bash shell is 6891. The process tree of this program is
showed below.
Exercise 2 (10 pts)
Compile and execute the program fork_ex1.c .
https:
github.com/ITF22519/labs
lo
maste
lab5/img/process_tree.png
XXXXXXXXXXlabs/lab5.md at master · ITF22519/labs
https:
github.com/ITF22519/labs
lo
maste
lab5/lab5.md 4/8
(1 pts) Include the output of the program.
(5 pts) Draw the process tree (label processes with PIDs).
(4 pts) Explain how the tree was built.
Make the new Process do Something Different
Since the fork() function call creates a clone of the parent process and returns different values for the parent and child processes. Using
these two return values, the child process can be made to do something that is not the same as the parent. Firstly, we can use the fact that
the value returned by fork() is zero for the child. To differentiate between which process is which, the simplest is to use an if statement.
Exercise 3 (5 pts)
The program fork_ex2.c prints different messages in the child and parent processes. Complete the condition of the if statements in this
program.
Waiting on the Child Process
When running the program fork_ex2.c , the parent and child process will each execute at their own pace, and either can finish execution
efore the other. In the event that this is not the desired behavior, there are two system calls that the parent can run that will guarantee
that the parent waits for the child process to exit. The two functions are wait() and waitpid() . Full information on what each of these
functions do and how they are used can be found at the manual page:
$ man 2 wait
To use wait() to make the parent process wait for the child process to complete, the following snippet of code is used:
#include
#include
...
int status = 0;
...
child = fork();
if(child == 0)
{
does something cool
}
else if(child > 0)
{
XXXXXXXXXXwait(&status);
XXXXXXXXXXprintf("child process is done, status is: %d\n", status);
XXXXXXXXXXreturn 0;
}
else
{
XXXXXXXXXXpe
or("fork");
XXXXXXXXXXexit(-1);
}
XXXXXXXXXXlabs/lab5.md at master · ITF22519/labs
https:
github.com/ITF22519/labs
lo
maste
lab5/lab5.md 5/8
This snippet will make sure that the parent suspends execution until one of its children terminates. In the event that there are multiple
children, and knowledge of a specific child process’ termination is of importance, then waitpid() should be used to tell the parent
process to wait. The code snippet to do that is:
#include
#include
...
int status = 0;
...
child = fork();
if(child == 0)
{
does something cool
}
else if(child > 0)
{
XXXXXXXXXXwaitpid(child, &status, 0);
XXXXXXXXXXprintf("child process is done, status is: %d\n", status);
XXXXXXXXXXreturn 0;
}
else
{
XXXXXXXXXXpe
or("fork");
XXXXXXXXXXexit(-1);
}
This will guarantee that the parent process wait for the child process with the process id stored in child to terminate before continuing.
Note that, as shown in the man pages for wait() , to make this snippet of code work like the previous snippet, change the value of the
first argument for waitpid() (the argument that is occupied by the variable child ) to -1 and the behavior of this snippet and the
previous snippet would be the same. So effectively:
wait(&status);
is the same as waitpid(-1, &status, 0);
The call to the wait() function results in a number of actions:
If the calling process has no children, wait() returns -1 .
If the calling process has a child that has terminated (a zombie), that child’s PID is returned and it is removed from the process table.
Otherwise, the call blocks (suspends the process) until a child terminates. The waitpid() function allows the WNOHANG flag to be
specified to return immediately in all cases.
It is highly recommended that the student read through the man page for wait() and waitpid() to fully understand how to use wait()
and waitpid() and experiment with multiple fork() and wait() programs until fully comfortable with what is actually happening. What
is presented here is merely a quick overview of how to use the two.
Exercise 4 (5 pts)
Summarize the usage of wait() and waitpid() .
Making a Process Run Another