layout | title | <!--license |
---|---|---|
default |
Working with processes |
- TOC {: toc}
This lab is concerned with processes:
- using job control commands to monitor and control the processes running in your system; and
- understanding the main Unix system calls for managing processes.
These exercises demonstrate the basic properties on processes under Unix like systems. Through these you should gain an understanding of what a process is, and the tools and techniques for managing processes.
-
Start a terminal window.
-
Type the command
ps
and note the processes it lists as running. -
Create a few processes. Do this by typing the command for the process but put an ampersand
&
after it.$ xlogo & $ xedit & $ xeyes & $ gedit & $ gvim &
{: .code}
-
You should now have a number of additional windows open. Find the Terminal window you had opened.
-
Type the command
ps
again and note the changes to the process list. The results of theps
command show the list of processes running under the terminal.- Why are no other process (such as the desktop) shown?
- from the
man
pages can you tell what information is in the results.
-
Now start xterm from the prompt in the terminal window.
$ xterm &
{: .code}
- In the (new) xterm window start another few processes.
- Run
ps -f
in- the new xterm window
- the original terminal window
- What differences do you see?
Again start a few processes in a terminal window as above.
- run
ps
again. - note the process id number for one of the processes (xlogo)
- type
kill -TERM <id>
. What happened? - run
ps
again - now try
kill -KILL <id>
on another process.
-
run
ps -f
what additional information does this tell you? -
run
ps -l
what additional information does this tell you? -
In a terminal (from above) use
$ ps --user your-id
{: .code} or if you’re a little lazy (like me),
ps --user $(whoami)
-
This shows all your processes. Could you see another user's processes?
-
Try the command
ps -e
, this should list all processes on the system. You may need to scroll the list.
-
In one of the windows you have open run
$ ps --user $(whoami) --forest
{: .code} Can you identify the ancestors of each process?
-
Now run
$ pstree
{: .code} Again, you may have to scroll back to see the whole list.
-
Unix start up: Look back through the full map of processes from pstree. You should see a process called
init
(orsystemd
) at the root of the tree.
Start another terminal and run top
, this gives a realtime
view of processes. (You can end it when you are ready by pressing q
)
- start a couple of applications from the desktop menu
- what changes do you see in the processes reported by
top
?
Develop your understanding of Unix's process management commands by working through this tutorial.
This section is concerned with the main process management system calls provided by the operating system. It uses the C API. The following program is the example from the lecture in week 4.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int globvar = 6;
int main(void) {
int var = 88;
pid_t pid;
int status;
printf("before fork\n");
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed\n");
exit(-1);
} else if (pid == 0) { /* child */
globvar++;
var++;
printf("pid = %d, globvar = %d, var = %d\n",
getpid(), globvar, var);
exit(0);
} else { /* parent */
waitpid(pid, &status, 0); // parent
printf("pid = %d, globvar = %d, var = %d, child status = %d\n",
getpid(), globvar, var, status);
}
}
{: .code}
Use a text editor to create this program. Save it into a file
called forkexample.c
. Compile the program: gcc -o forkexample forkexample.c
,
and run it: ./forkexample
.
- What is the process id of
forkexample
? - What is the process id of its child process?
- What are the values of
globvar
andvar
inforkexample
just before it terminates? - What are the values of
globvar
andvar
in the child process just before it terminates? - What do your answers to the previous questions tell you about the organisation
of a process's memory after
fork()
?
Here's a slightly different version of the forkexample
program. It waits for the
user to press before terminating the parent and child processes. This
gives you a chance to use the ps
command to see the processes being created and
destroyed.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int globvar = 6;
int main(void) {
int var = 88;
pid_t pid;
printf("before fork\n");
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed\n");
exit(-1);
} else if (pid == 0) {
globvar++; //child
var++;
} else {
waitpid(pid, NULL, 0); // parent
}
printf("pid = %d, globvar = %d, var = %d\n",
getpid(), globvar, var);
if (pid == 0) {
printf("Press <ENTER> to end the child ... ");
while (getchar() != '\n') {};
} else {
printf("Press <ENTER> to end the parent ... ");
while (getchar() != '\n') {};
}
exit(0);
}
{: .code}
-
Build this program.
-
Use the
ps
command to discover what terminal id has been given to your terminal. For example$ ps PID TTY TIME CMD 2637 pts/6 00:00:00 bash 4086 pts/6 00:00:00 ps
{: .code} shows that this terminal is associated with
pts/6
; the information is in the column headedTTY
. -
Now run your new
forkexample
program and before you press enter to terminate anything, start up a new terminal and use theps
command to see what processes there are in the old terminal. For example$ ps -t pts/6
{: .code} Note: You'll need to use your own terminal id, not necessarily
pts/6
. -
Press ENTER in the terminal where
forkexample
is running. Check the processes in the other terminal usingps
. Do that again to terminate the parent process and useps
again to see what has happened. -
Replace the line
waitpid(pid, NULL, 0);
withsleep(60);
. Build the program and then go back to 3. Do you observe any differences in the output ofps
? -
What does this tell you about process creation and destruction?
Here's a simple example of using exec()
.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(void) {
pid_t pid;
char *args[] = {"ls", "-l", NULL};
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed\n");
exit(-1);
} else if (pid == 0) { // child
execl("/bin/ls", "ls" "-l", NULL);
} else { // parent
waitpid(pid, NULL, 0);
}
exit(0);
}
{: .code}
Replace the execl()
line with a line that uses each of the following functions
execlp()
,execv()
execvp()
to give 3 more programs that have the same behaviour.