Lab 3 (5 points)
CS550, Operating Systems
Introduction to C-Style Pointers, C-Style Strings, POSIX Threads, and Processes

Name: _____________________________________________

This assignment is based upon the UNIX labs from the CS2351 course at Oklahoma State University, previously available at cs.okstate.edu/newuser/index.html. To submit this assignment, you may copy and paste the assignment into a text editor such as nano, vi, notepad, MS Word, OpenOffice Writer, etc.  Enter your answers into the document and submit it to the dropbox for lab 3.  The purpose of this lesson is to learn to about command line debugging, pointers, threads, and processes in the C programming language.

1. Enter, compile, and run the following application:

#include <stdio.h>

int main(int argc, char ** argv)
{
  int arr[3] = {1,2,3};
  int x = 7;
  int * intPointer = &x;  //This is an integer pointer and contains the
                          //address of x.

  printf("Welcome to C!\n");
  printf("arr contains %d, %d, and %d\n", arr[0], arr[1], arr[2]);

  printf("x is %d, the address of x is %u, the address of arr is %u\n", x, intPointer, arr);

  //Notice that an integer pointer can also hold the address of an integer array.
  intPointer = arr;
  printf("The address of arr is %u\n", intPointer);

  //The * operator, when applied to a pointer, dereferences a pointer or an address
  intPointer = &x;

  printf("Dereferencing the address of x gives its value, which is %d\n", *intPointer);

  printf("Dereferencing arr provides arr[0] which is %d\n", *arr);
  printf("Dereferencing arr+1 provides arr[1] which is %d\n", *(arr+1));
  printf("Dereferencing arr+2 provides arr[2] which is %d\n", *(arr+2));

  return 0;
}

You may type this file into the nano text editor, or copy and paste it.

PuTTY users will open PuTTY and connect to the LittleFe server as shown in class.  Log on to LittleFe and create a new file called Welcome.c with the nano editor.  Users wishing to copy and paste the text into nano should return to this webpage, highlight the text of the source code, right click, and click copy.  Return to the nano editor, and right click inside the editor.  The text of the source code should now be inside the editor.  Press Ctrl-X to save and exit from nano.

Non-PuTTY users will log on to LittleFe as usual and create a new file called Welcome.c with the nano editor.  Users may copy the code from this website.  When inside the nano editor, right click and choose paste. The text of the source code should now be inside the editor.  Press Ctrl-X to save and exit from nano.

Introduce the following errors, one at a time to the program Welcome.c.  Compile the program and write down any error messages that the compiler produces.  Fix the previous error message before you introduce a new error.  If no errors were produced, explain why.

a. Change argc to argx.

b. Change Welcome to welcome.

c. Remove the first quote in the printf statement.

d. Remove the last quote in the printf statement.

e. Change main to mai.

f. Change printf to println.

g. Remove the semicolon at the end of the printf statement.

h. Remove the last curly bracket in the program.

i. Remove arr[0], arr[1], and arr[2] from the second printf statement.

j. Change arr[0] to arr[4].

k. Change arr[0] to arr[50000] (this should cause a segmentation fault).


2. Complete, compile, and run the following application.  Name it Lab3.c

You may copy and paste the following code into nano while using PuTTY or another ssh client.

// <Name>
// cs550
// Lab3

#include <stdio.h>

int main(int argc, char ** argv)
{
  char str[300];
  int iX;
  double dX;

  //Prompt the user to enter a line of text.
  printf("Please enter a line of text (less than 300 characters): ");

  //Use fgets to store a line of text from stdin in str.

  //Prompt the user to enter an integer.
  printf("Enter an integer: ");

  //Use scanf to store the integer in iX.

  //Prompt the user to enter a double.
  printf("Please enter a real number: ");

  //Use fgets and sscanf to store the double value in dX.

  //Print the results.
  printf("%s %d %lf\n", str, iX, dX);
  return 0;
}

Complete the code above, providing the necessary statements to store a C string, an integer, and a double provided by the user.  Save the values and turn in a printout (i.e. a copy) of your code and output.

To create an output file, use the UNIX command script:

$script Lab3.out
Script started, file is Lab3.out
$cat Lab3.c

<code is automatically printed here via the cat command>

$gcc Lab3.c -o Lab3.exe
$./Lab3.exe

<run the program to completion>

$exit
Script done, file is Lab3.out

Copy your file from the LittleFe system to your own system using SFTP (the Secure File Transfer Protocol).  Instructions for an sftp client are provided at the following site: http://catpages.nwmissouri.edu/m/monismi/cs550/examples/sftp.html


3. The following program prints hello from ten POSIX (Portable Operating System Interface) threads.  Read through the following program and run it.  Provide a copy of your output when you submit the assignment.

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NUM_THREADS 10
//Add your static array here

//Define our thread function
void * HelloThread(void * threadId)
{
  long tid;  // This thread's identifier
  tid = (long) threadId;
  //Modify the static array here

  printf("Hello from thread %ld\n", tid);

  pthread_exit(NULL); //Cause the thread to die.
}

int main(int argc, char ** argv)
{
  pthread_t threadList[NUM_THREADS];  //Declare and allocate memory for t$
                                      //list of threads

  int returnCode;
  long i;  //Counter to keep track of the current thread

  for(i = 0; i < NUM_THREADS; i++)
 {
    printf("From main, creating thread %ld\n", i);

    //Create the threads storing the thread identifier in the thread
    //list.  Note that we pass in the name of the function that will
    //act as the thread as the third parameter, and the following
    //parameters are the parameters passed into the thread.

    returnCode = pthread_create(&threadList[i], NULL, HelloThread,
      (void *) i);

    if(returnCode != 0)
    {
      printf("The return code from thread %ld is %d\n", i, returnCode);
      exit(-1);
    }
  }

  //Print the static array here

  //Kill the main thread
  pthread_exit(NULL);
}

To compile the program above assuming it is named lab3Threads.c, use the following command on any Linux system:

gcc lab3Threads.c -pthread -o lab3Threads.exe

4. The following program creates ten processes and prints hello from each of them.  Read through the program and run it.  Include your output with your submission.

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define NUM_PROCESSES 10
//Declare your static array here

int main(int argc, char ** argv)
{
  pid_t pid;
  int i;

  //Fork a child process
  for(i = 0; i < NUM_PROCESSES; i++)
  {
    pid = fork();

    if(pid < 0)
    {
      fprintf(stderr, "Fork failed\n");
      return 1;
    }
    else if(pid == 0)
    {
      //Each child process starts here
      //Modify the static array here
      printf("Child %d complete!\n", i);
      exit(0);
    }
    else
    {
      //parent process
      printf("Parent started process %d\n", i);
    }
  }
  wait(NULL);
  printf("Finished parent process\n");
  return 0;
}

To compile the program above, assuming it is called lab3Processes.c, use the following command:

gcc lab3Processes.c -o lab3Processes.exe

5. Add a static integer array of size NUM_THREADS immediately after the line containing the #define in the thread program from problem 3.  The code for this array follows below.

static int arr[NUM_THREADS];

Set arr[(int) tid)] to a value of your choice within each thread.  Note that this value must be different for every thread.  It could be the same as the thread identifier, if you wish.

Print the contents of this array immediately before you kill the main thread.

Include a copy of your source code and the output in your submission.

6. Repeat problem 5 using processes instead of threads for the program in problem 4.  Why is the output different?  Hint: think about process memory space.

7. Compile and run the following program on Stampede (Host Name: stampede.tacc.utexas.edu ).  You should be able to login to Stampede using PuTTY and your Stampede username.  Note that you are not allowed to run your program (also called a job) on the login node.  Instructions to submit, run, check, and, if necessary, to kill a job follow after the program.  Note that Stampede runs a variation of Linux called CentOS.  Most of the commands you used on Littlefe such as ps, ls, cat, nano, etc., work on Stampede. 

#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"

int main (int argc, char** argv)
{
  int number_of_processes;
  int my_rank;
  int mpi_error_code;

  mpi_error_code = MPI_Init(&argc, &argv);

  mpi_error_code = MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  mpi_error_code = MPI_Comm_size(MPI_COMM_WORLD, &number_of_processes);

  printf("%d o%d: Hello, world!\n", my_rank, number_of_processes);

  mpi_error_code = MPI_Finalize();
}

Save this program in a file named hello_world.c on Stampede. 

On Stampede, you must submit batch scripts to run your programs.  This means your job waits in a virtual line before it may run.  The batch queue scheduler on Stampede is called SLURM (like the drink on Futurama).  Write a SLURM batch script for your program as follows:

#!/bin/bash
#SBATCH -A TG-SEE120004  #Account number
#SBATCH -n 16            #Number of tasks (cores)
#SBATCH -J helloWorld    #Job name
#SBATCH -o hw.o%j      #Output file name
#SBATCH -p normal        #Queue to use
#SBATCH -t 00:15:00     #Run (wall) time 15min
ibrun hello_world.exe

Save this batch script in a file called hello.sbatch on Stampede.

Compile your program on the head node using the following command.  Note that this is ok because the compilation uses very few resources.

mpicc hello_world.c -O3 -o hello_world.exe

Note that the executable file name matches exactly with what will run in the batch script using ibrun.

Fix any errors in your program, and submit your program to the batch queue using the following command:

sbatch hello.sbatch

Once your program finishes, the output will show up in a file called hw.oJobNumber, where JobNumber is the job number assigned to your job by Stampede.  You can find this file by using the ls command.  Turn in the contents of this file.

While your program is in the batch, run the following commands on Stampede.  If necessary, submit your program to the batch queue again and quickly run the commands below.  Note that the up and down arrow keys can be used to scroll through previously issued commands.

showq

What happened after running showq?

squeue -u Username

Where Username is your Stampede username.  What happened after running the command above?

Note that you may have a program that runs in an infinite loop or enters a condition called deadlock or livelock.  To end such a program that is running on Stampede, you may first determine the job number using squeue as shown above and killing the program with the following command:

scancel JobNumber