Final Exam

You are tasked with writing a client that connects and communicates with a running server.  The server information is below.

  • Server IP address: 23.22.136.170
  • Port: 8902
  • Service name: final

To complete this exam you will need to edit your /etc/services file.

Source code

Please log into your AWS server and create a folder named final in your Git repository.  Include all of your source code for this exam in the final folder and push the folder to Github at the end of the exam period or when you are finished.

Before leaving, please check GitHub.com to be certain that your files were successfully added to your repository.

Protocol

The server uses the following protocol.

  • Client sends an 8 bytes string containing your username.
  • Server sends 16 bytes containing a null terminated string holding your IP address.
  • Client sends a 4 byte integer whose value is the sum of the numbers separated by dots in the IP address.
  • If the sum is correct, the server sends a 256 byte null terminated string containing a quote.

Grading Rubric

  • 5 points if your program is well formatted and includes proper error checking.
  • 20 points if the server receives your username from your client.
  • 20 points if your client prints to the console the IP address received from the server.
  • 20 points if the server receives the correct sum from your client.
  • 15 points if you include a README file that contains the quote sent from the server.
  • 5 points if your client gracefully terminates using a signal handler for SIGINT.
  • 5 points if your client uses the string read from the server (containing the IP address) to compute the sum.
  • 10 points if your client uses a thread to compute the sum.

Students that submit programs that do not compile or that get segmentation faults will receive a grade of 0.  Therefore, before pushing your code to GitHub, please be sure to comment out all blocks of code that can not be compile or that produced segmentation faults.

Restrictions on Computer Use

You may view any resources available on the internet during this exam.  You may not, however, communicate with anyone, anonymous or not, in order to receive or give help.  When in doubt, raise your hand and ask.

Good Luck!

 

Creating a Linux VM in the AWS Cloud

Due: Prior to class on Friday, January 25

Please follow the instructions in the following tutorials.  The first shows you how to create an AWS account and register for AWS Educate which will provide you $100 free credit for your AWS account.  The second will show you how to set up a Linux instance in the AWS cloud.

  1. Creating an Amazon Web Services Account
  2. Launch a Linux Virtual Machine

 

 

Fork Bomb

On your AWS instance do the following:

  1. Clone your GitHub repository.  See this tutorial if you need help cloning your repository.
  2. Add a directory named bomb to your repo.
  3. Inside the bomb directory, write a program named bomb.c that creates a fork bomb (i.e. a program that creates infinitely many child processes).
  4. Run your program.
    1. After you run your program, you’ll notice that you are no longer able to use the Linux instance.
    2. Stop your instance (do not Terminate it) from the AWS console.  It may take a few minutes for it to stop.
    3. Restart your instance and log back in.
  5. Push your code to GitHub.

Resource Limits

Due: prior to midnight on Friday, February 1

Please place all of your code in a directory named rlimits.

This assignment will provide practice using the following system functions.

  • getrlimit(): get the current and maximum limits of a system resource
  • setrlimit(): set the current limit of a system resource
  • strerror(): get the string corresponding to the current value in the global variable errno
  • fork(): create a child process
  • execl():  change the .text section of a child process
  • sleep(): pause a process

Program Description

The experiment you are about to conduct will have 2 programs: we’ll call them the parent program and the child program.  Place them in files named parent.c and child.c.

The child program is simple. It simply prints the number in argv[1] that is passed to it and then terminates.

The parent program should do the following:

  • First, limit the number of child processes that it can create using getrlimit() and setrlimit().  Limit the number of child processes to 7.
  • Initialize a counter that should be incremented in each iteration of the loop.
  • Test that the limit works by entering an infinite-loop. In the loop the program should do the following:
    • Call fork() to create a child process.
    • If fork() is successful, the child process should call execl() to run the child program passing to the child program the value of the counter, and the parent process should print the child’s pid.
    • If fork() is unsuccessful, the parent should use strerror() to print the string that corresponds to the error code stored errno, pause for 2 seconds using sleep(), and then terminate.

Below is a screen shot of the output for a working solution.

Riddle

In the program that I wrote, shown running in the above screenshot, I limited the number of child processes to 7.  The program worked correctly and failed after creating 2 child processes.  Why is this correct?

Programming Tips

To set a limit on the number of processes a user can have (e.g. 7), first call getrlimit() to initialize the struct rlimit variable.  After calling getrlimit() change the value of rlim_cur and then call setrlimit().

When a system call fails, print a readable string corresponding to the value in errno.  To do so include <errno.h> and use a statement similar to the one below.

printf("setrlimit failed: %s\n", strerror(errno));

To pass the counter to execl(), you need to store the integer in a string.  To do so, you can use snprintf as shown below.

int count = 0;
char buff[8];
...

snprintf(buff, sizeof(buff), "%d", ++count);

To change the .text section of the child process (i.e. change the program that the child is running) you can use execl() as shown below.  Note: you should definitely check the return value of execl().

execl("./child", "child", buff, NULL)

When the parent process dies, the command prompt is immediately printed to the console.  This may happen before the child processes run and print their statements.  To avoid this behavior simply call the sleep(2) right before the parent terminates.  This will cause the parent to pause for 2 seconds, giving the child processes enough time to print their statements before the command prompt is printed.

Grading

  • Program does not check return value from all system call (-2 for each occurrence)
  • Improper use of the value returned from fork (-5)
  • Missing or misplaced call to sleep (-2)
  • Call fork more than once (-5)
  • Call exec more than once (-5)
  • Set limit on number of processes improperly (-5)
  • Improperly pass the child counter to exec (-5)
  • In the child’s block, after exec, have code that will never execute (-2)
  • After call to exit, have code that will never execute (-2)
  • Includes unnecessary global variables (-2)
  • Parent process does not print the child’s pid (-5)
  • Strerror is not called within printf statements (-2)
  • Invalid call to exec (-5)