Skip to content

Latest commit

 

History

History
282 lines (221 loc) · 7.39 KB

L05.md

File metadata and controls

282 lines (221 loc) · 7.39 KB
layout title <!--license
default
Working with processes
  • TOC {: toc}

Introduction

This lab is concerned with processes:

  1. using job control commands to monitor and control the processes running in your system; and
  2. understanding the main Unix system calls for managing processes.

Job control

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.

The ps Command

  1. Start a terminal window.

  2. Type the command ps and note the processes it lists as running.

  3. 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}

  4. You should now have a number of additional windows open. Find the Terminal window you had opened.

  5. Type the command ps again and note the changes to the process list. The results of the ps 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.
  6. 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?

Stopping a Process

Again start a few processes in a terminal window as above.

  1. run ps again.
  2. note the process id number for one of the processes (xlogo)
  3. type kill -TERM <id>. What happened?
  4. run ps again
  5. now try kill -KILL <id> on another process.

The ps Command - Options

  1. run ps -f what additional information does this tell you?

  2. run ps -l what additional information does this tell you?

  3. In a terminal (from above) use

    $ ps --user your-id

    {: .code} or if you’re a little lazy (like me), ps --user $(whoami)

  4. This shows all your processes. Could you see another user's processes?

  5. Try the command ps -e, this should list all processes on the system. You may need to scroll the list.

Process Tree

  1. In one of the windows you have open run

    $ ps --user $(whoami) --forest

    {: .code} Can you identify the ancestors of each process?

  2. Now run

    $ pstree

    {: .code} Again, you may have to scroll back to see the whole list.

  3. Unix start up: Look back through the full map of processes from pstree. You should see a process called init (or systemd) at the root of the tree.

The top command

Start another terminal and run top, this gives a realtime view of processes. (You can end it when you are ready by pressing q)

  1. start a couple of applications from the desktop menu
  2. what changes do you see in the processes reported by top?

Further work

Develop your understanding of Unix's process management commands by working through this tutorial.

Unix system calls: fork(), exec(), wait(), exit()

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.

  1. What is the process id of forkexample?
  2. What is the process id of its child process?
  3. What are the values of globvar and var in forkexample just before it terminates?
  4. What are the values of globvar and var in the child process just before it terminates?
  5. 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}

  1. Build this program.

  2. 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 headed TTY.

  3. Now run your new forkexample program and before you press enter to terminate anything, start up a new terminal and use the ps 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.

  4. Press ENTER in the terminal where forkexample is running. Check the processes in the other terminal using ps. Do that again to terminate the parent process and use ps again to see what has happened.

  5. Replace the line waitpid(pid, NULL, 0); with sleep(60);. Build the program and then go back to 3. Do you observe any differences in the output of ps?

  6. 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

  1. execlp(),
  2. execv()
  3. execvp()

to give 3 more programs that have the same behaviour.