Starting from:
$30

$24

Forks Solution

Objective: To understand fork, exec, and pipes.




This document should help you with Making a Makefile.docx




Example program and data: hw3example.zip which will only work on Linux. To unzip, type "unzip hw3example.zip" (NOTE: you only need to include wall or CPU time in your program.)




 




The idea is for you to create a program that reads a binary random access file and finds the min and max. Your program will either use one process or it will use four processes (parallel computing) to achieve the answer. In order for your forked processes to work they must use pipes.




 




Instructions:




- Create at least two c programs to complete the following:

- From the command prompt the user will run the following: "hw3 numForks fileName"

- "numForks" can only be "1" or "4" - it indicates the number of processes that will be run.

- "fileName" is the name of the binary random access file that will be used, generated by a program below.

- If "1" is entered then the program calls exec on another c program that will return the max and min of the file to the user.

- if "4" is entered then the program calls fork an appropriate number of times and calls exec on another program the appropriate times and ways and will return the max and min of the file to the user. Your program will need to use pipes to communicate between forked processes.

- Regardless of "1" or "4" being entered, the program will report how much time it took to process the file.

- When the program runs your name is printed out.

- The first c program will take care of the command line arguments and possibly deal with forking.

- A second c program will actually figure out the min and max from the file.

- A third, fourth, fifth, etc. c programs may be created, but use caution to not confuse yourself.

- Create a Makefile that compiles all of your c programs when the user types 'make' from the command prompt. If your programs do not compile with 'make' then you get zero points.




The grader will create a random access binary file that he will use for grading all assignments. The code that he will use is at the bottom of this page.




### Deliverable:




Zip up all you files, including the Makefile, and submit it to Canvas by the due date.




Tips:




- Start early.

- Get the write program (see below) working first

- Get the read program (see below) working next.

- Make the minMax program.

- Get the Makefile to work.

- Get exec to work.

- Get fork to work.

- Learn. Live. Love. :)




Note 1:




We will be using Linux as the target grading system. However, You may use other environments for development, but they may not work the same as your Linux virtual machine.




Note 2:




The input file size is not determined. The grader may have 5 numbers in the file or five trillion.




The code used for generating the file:




```c

/*

* This file generates a binary output file containing integers. It

* requires the output filename as a parameter and will take an

* argument indicating the number of values to generate as input.

*/

#include <stdio.h

#include <stdlib.h

#include <string.h

#include <time.h




#define BIAS 0 // a bias value added to the numbers to "bias" the file

// contents to provide an offset to the min and max




int main(int argc, char * argv[]) {

const char * filename; // name of the output file

FILE * ft; // file handle for output file

int numtogen = 1000000; // default is to generate 1,000,000 numbers

int randomnum, i; // variables used in the loop generating numbers

 

if (argc<2) { // not enough arguments, need output file name

printf("Usage: gendata <filename [number of numbers]\n");

return 1;

}

if (argc == 3) // optional third argument for number of numbers

numtogen = atoi(argv[2]);

 

filename=argv[1]; // use the filename entered to store numbers

srand(time(NULL)); // seed the random number generator

ft= fopen(filename, "wb") ;

if (ft) {

for (i = 0; i < numtogen; i++){

randomnum = rand() % numtogen + BIAS;

fwrite(&randomnum,sizeof(int),1,ft);

}

fclose(ft);

}

return 0;

}

```




Example code of how to read from the file:

```c

/*

* This is a sample program, showing how to read the file.

*/

#include <stdio.h

#include <stdlib.h

#include <string.h

#include <unistd.h

#include <sys/types.h




int main(int argc, char * argv[]) {

const char * filename; // name of file to read

FILE * ft; // file handle for the file

int pid, // process id of this process

num, // the number of integer values in the file

i, // loop control variable for reading values

temp=0; // used to store each value read from the file

long size; // size in bytes of the input file

/*********************************************************************/

 

if (argc<2) { // not enough arguments, need output file name

printf("Usage: readfile <filename\n");

return 1;

}

filename = argv[1]; // read the file named on the command line

 

ft= fopen(filename, "rb") ;

if (ft) {

pid = getpid();

fseek (ft,0,SEEK_END); //go to end of file

size = ftell(ft); //what byte in file am I at?

fseek (ft,0,SEEK_SET); //go to beginning of file

num = (int)size / (int)sizeof(int); // number of integer values

printf("file size: %li bytes\n", size);

printf("sizeof(int) = %i bytes\n",(int) sizeof(int));

printf("how many integers = %i\n\n", num);

// now read and print out the values

for(i = 0; i < num; i++){

fread(&temp,sizeof(int),1,ft);

printf("%5i: %7i ",pid,temp);

if ((i+1)%5 == 0)

printf("\n");

}

fclose(ft); // close the file now that we're done

}

printf("\n"); // only have a tab on last line so newline

return 0;

}

```




Example of exec and pipe:

Program that will be called using exec named "printstuff":

```c

/*

* This program prints all the natural numbers less than the

* number passed as a parameter

*/

#include <stdlib.h

#include <stdio.h




int main(int argc, char *argv[]) {

int i; // used as a for-loop control variable

int max; // the integer value of the first parameter




printf("Number of command line arguments, argc = %d\n",argc);

printf("The zeroeth argument, the program name, argv[0] = %s\n",argv[0]);

if (argc != 2) {

printf("Incorrect number of arguments, you must pass in a number.\n");

return -1;

} else {

printf("The first argument, a string value: %s\n",argv[1]);

}

max = atoi(argv[1]); // convert the string to an integer

for(i = 0; i < max; i++) {

printf("%5i\t",i);

if((i+1)%10 == 0)

printf("\n");

}

printf("\n");

return 5;

}

```




Exec example (calls the above program):

```c

/*

* This program creates a child process that it communicates

*/

#include <stdlib.h

#include <stdio.h

#include <unistd.h




int main() {

int cp[2]; // integer array for the pipes

int pid = 0; // process id of this proccess

char ch; // character read from the pipe

 

printf("This is before the fork.\n");

if (pipe(cp) < 0) {

printf("didn't work, couldn't not establish pipe.\n");

return -1;

}




pid = fork();

if (pid == 0) {

printf("this is the child. not the original\n");

close(1); //close stdout

dup2(cp[1], 1); //move stdout to pipe of cp[1]

close(0); //close stdin

close(cp[0]); //close pipe in

//note: All the arguments in exec have to be strings.

// with an extra null string to end the args

execl("printstuff","printstuff", "5",(char *) 0);

} else {

close(cp[1]); //if you don't close this part of the pipe

// then the while loop (three lines down) will never return

printf("this is the parent. the 'original.'\n");

while( read(cp[0], &ch, 1) == 1) {

printf("%c",ch);

//write(1, &ch, 1);

//outcount++;

}

printf("all done.\n");

//execl("printstuff","printstuff", "10",(char *) 0);

}

printf("This is after the fork.\n");

return 0;

}

```

More products