###########################################################
#
# Makefile
# HW05 by Cameron Chrobocinski
#
###########################################################
process1: clean process1.o process2.o process3.o
g++ process1.o -o process1
g++ process2.o -o process2
g++ process3.o -o process3
process1.o: process1.cpp
g++ -c process1.cpp -o process1.o
process2.o: process2.cpp
g++ -c process2.cpp -o process2.o
process3.o: process3.cpp
g++ -c process3.cpp -o process3.o
clean:
/bin/rm -f *.o *~ process1 process2 process3 P1.txt P2.txt P3.txt
010010000110010101101100011011000110111100100000010101110110111101110010011011000110010000100001
/***********************************************/
// Author: Cameron Chrobocinski
// Class: Systems Programming
// Assignment: HW05
/***********************************************/
#include <iostream>
#include <sys/types.h>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sstream>
#include <cstring>
using namespace std;
void sig_handler(int signo){
if(signo == SIGCONT)
cout << "Process 1: Received SIGCONT.\n";
else if(signo == SIGINT)
cout << "Process 1: Received SIGINT.\n";
else if(signo == SIGUSR1)
cout << "Process 1: Received SIGUSR1.\n";
}
int main(){
//Ensure that the execution environment is sterile
system("/bin/rm -f P1.txt P2.txt P3.txt");
//Signal handler
if(signal(SIGCONT, sig_handler) == SIG_ERR)
cerr << "Process 1: Failed to catch SIGCONT.\n";
//Declare variables
pid_t pid; //pid for storing this process's ID
pid = getpid(); //pid equals this process's ID
pid_t process2; //process2 for storing process 2's ID
pid_t process3; //process3 for storing process 3's ID
string temp; //temp for storing various strings
cout << "Process 1: Initiated.\n";
//Save PID to P1.txt
ofstream P1("P1.txt"); //P1 for storing process 1's ID in P1.txt
if(!P1.is_open()){ //if P1 is not open.
cerr << "Process 1: P1.txt failed to open\n"; //.tell user that P1 did not open
return -1; //.return with error
}else { //else.
P1 << pid; //.store process 1's ID in P1.txt
P1.close(); //.close P1
cout << "Process 1: " << pid << " has been written to file P1.txt\n"; //.tell user what process 1's ID is
}
//Access message.txt
ifstream message; //message for reading from message.txt
message.open("message.txt"); //open message.txt
if(message.fail()){ //if opening message.txt failed.
cerr << "Process 1: message.txt failed to open\n"; //.tell user that opening message.txt failed
return -1; //.return with error
}else //else.
cout << "Process 1: message.txt opened successfully.\n"; //.tell user that message.txt was opened successfully
if(fork()){
//Wait for other processes to write to their files
cout << "Process 1: Paused...\n"; //tell user that process 1 is paused
pause(); //wait for process 2
if(fork()){
//Wait for other processes to write to their files
cout << "Process 1: Paused...\n"; //tell user that process 1 is paused
pause(); //wait for process 2
//Here, process 3 will store its ID in P3.txt, then pause for process 2.
//Then, process 2 will store its ID in P2.txt, read process 1's and process 3's ID's, then signal to process 1.
//Then, process 2 will read process 3's ID then signal back to process 1.
//Read PID from P2
ifstream P2("P2.txt"); //P2 for reading from P2.txt
if(!P2.is_open()){ //if opening P2.txt failed.
cerr << "Process 1: P2.txt failed to open\n"; //.tell user that opening P2.txt failed
return -1; //.return with error
}else //else.
cout << "Process 1: P2.txt opened successfully.\n"; //.tell user that P2.txt opened successfully
P2 >> temp; //read PID from P2.txt
process2 = atoi(temp.c_str()); //convert process 2's PID to an int and store in a pid_t
cout << "Process 1: Read " << process2 << " from P2.txt\n"; //tell user what process 2's ID is
P2.close(); //close P2
//Wait for process 2 to start its while loop
if(kill(process2, SIGCONT) == -1)
cerr << "Process 1: Failed to send the SIGCONT signal to process 2.\n";
else
cout << "Process 1: Successfully sent the SIGCONT signal to process 2.\n";
cout << "Process 1: Paused...\n";
pause();
//Here, process 2 will begin its while loop, then signal to process 1.
message >> temp; //Store the message in temp
char c; //c for getting one char at a time from temp
//Send each char in temp to process 2
for(int i = 0; i < temp.length(); i++) { //for each char in temp.
c = temp[i]; //.store the char in c
//.
if(c == '0'){ //.if c is 0.
if(kill(process2, SIGUSR1) == -1) //..send SIGUSR1 to process 2
cerr << "Process 1: Failed to send the SIGUSR1 signal to process 2.\n"; //..
else{ //..
cout << "Process 1: Successfully sent the SIGUSR1 signal to process 2.\n"; //..
cout << "Process 1: Paused...\n"; //..
pause(); //..pause process 1
//Here, process 2 will send SIGUSR1 to process 3.
//Then, process 3 will append '0' to its message and signal back to process 2.
//Then, process 2 will signal back to process 1.
} //..
}else if(c == '1'){ //.else if c is 1.
if(kill(process2, SIGUSR2) == -1) //..send SIGUSR2 to process 2
cerr << "Process 1: Failed to send the SIGUSR2 signal to process 2.\n"; //..
else{ //..
cout << "Process 1: Successfully sent the SIGUSR2 signal to process 2.\n"; //..
cout << "Process 1: Paused...\n"; //..
pause(); //..pause process 1
//Here, process 2 will send SIGUSR2 to process 3.
//Then, process 3 will append '1' to its message and signal back to process 2.
//Then, process 2 will signal back to process 1.
} //..
}else{ //.else.
cerr << "Character encountered in mesage.txt that is not 1 or 0. Aborting execution.\n"; //..tell user that there was an error
if(kill(process2, SIGINT) == -1) //..send SIGINT to process 2
cerr << "Process 1: Failed to send the SIGINT signal to process 2.\n"; //..
else{ //..
cout << "Process 1: Successfully sent the SIGINT signal to process 2.\n"; //..
cout << "Process 1: Paused...\n"; //..
pause(); //..pause process 1
//Here, process 2 will send SIGINT to process 3.
//Then, process 3 will break out of its while loop, print its message, signal back to process 2, and terminate.
//Then, process 2 will break out of its while loop, signal back to process 1, and terminate.
return -1; //..exit with error
} //..
} //.
} //
cout << "Process 1: Message sent was " << temp << endl; //tell user what message was sent
if(kill(process2, SIGINT) == -1) //send SIGINT to process 2
cerr << "Process 1: Failed to send the SIGINT signal to process 2.\n"; //
else{ //
cout << "Process 1: Successfully sent the SIGINT signal to process 2.\n"; //
cout << "Process 1: Paused...\n"; //
pause(); //pause process 1
} //
message.close(); //close message
cout << "Process 1: Terminated.\n"; //tell user that process 1 is terminating
return 0; //exit normally
} else { //child 2 code in this block.
system("./process3"); //.run process 3
exit(0); //.terminate child
}
} else { //child 1 code in this block.
system("./process2"); //.run process 2
exit(0); //.terminate child
}
//program should not reach this point I think, return -1
return -1;
}
/***********************************************/
// Author: Cameron Chrobocinski
// Class: Systems Programming
// Assignment: HW05
/***********************************************/
#include <iostream>
#include <sys/types.h>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string>
using namespace std;
int sig_ret;
void sig_handler(int signo){
if(signo == SIGUSR1){
cout << "Process 2: Received SIGUSR1.\n";
sig_ret = 0;
}else if(signo == SIGUSR2){
cout << "Process 2: Received SIGUSR2.\n";
sig_ret = 1;
}else if(signo == SIGINT){
cout << "Process 2: Received SIGINT.\n";
sig_ret = 2;
}else if(signo == SIGCONT){
cout << "Process 2: Received SIGCONT.\n";
sig_ret = 3;
}
}
int main(){
//Define some more signal handlers
if(signal(SIGCONT, sig_handler) == SIG_ERR){ //Signal handler for SIGCONT
cerr << "Process 2: Failed to catch SIGINT.\n"; //
}else if(signal(SIGINT, sig_handler) == SIG_ERR){ //Signal handler for SIGINT
cerr << "Process 2: Failed to catch SIGINT.\n"; //
}else if(signal(SIGUSR1, sig_handler) == SIG_ERR){ //Signal handler for SIGUSR1
cerr << "Process 2: Failed to catch SIGUSR1.\n"; //
}else if(signal(SIGUSR2, sig_handler) == SIG_ERR){ //Signal handler for SIGUSR2
cerr << "Process 2: Failed to catch SIGUSR2.\n"; //
}
//Declare variables
pid_t pid; //pid for this process's ID
pid = getpid(); //pid equals this process's ID
pid_t process1; //process1 for process1's ID
pid_t process3; //process3 for process3's ID
string temp; //temp for storing various strings
cout << "process 2: Initiated.\n";
//Save PID to P2.txt
ofstream P2("P2.txt"); //P2 for writing to P2.txt
if(!P2.is_open()){ //if P2 did not open.
cerr << "Process 2: P2.txt failed to open.\n"; //.tell user that P2 failed to open
return -1; //.exit with error
}else { //else.
P2 << pid; //.store process 2's ID in P2.txt
P2.close(); //.close P2
cout << "Process 2: " << pid << " has been written to file P2.txt.\n"; //tell user what process 2's ID is
} //
//Read PID from P1
ifstream P1("P1.txt"); //P1 for reading from P1.txt
if(!P1.is_open()){ //if opening P1.txt failed.
cerr << "Process 2: P1.txt failed to open.\n"; //.tell user that opening P1.txt failed
return -1; //.return with error
}else //else.
cout << "Process 2: P1.txt opened successfully.\n"; //.tell user that P1.txt opened successfully
P1 >> temp; //get process 1's ID from P1.txt
process1 = atoi(temp.c_str()); //convert process 1's PID to an int and store in a pid_t
cout << "Process 2: Read " << process1 << " from P1.txt\n"; //tell user that process 2 read process 1's ID
P1.close(); //close P1
//Signal to process 1 that processes 2 is ready
if(kill(process1, SIGCONT) == -1) //send SIGCONT to process 1
cerr << "Process 2: Failed to send the SIGCONT signal to process 1.\n"; //
else //
cout << "Process 2: Successfully sent the SIGCONT signal to process 1.\n"; //
cout << "Process 2: Paused...\n"; //tell user that process 2 is pausing
pause();
//Read PID from P3
ifstream P3("P3.txt"); //P3 for reading from P3.txt
if(!P3.is_open()){ //if opening P3.txt failed.
cerr << "Process 2: Error opening P3.txt\n"; //.tell user that opening P3.txt failed
cout << "Process 2: Paused...\n"; //.tell user that process 2 is pausing
pause(); //.pause process 2
//The most likely cause of P3.txt not opening is that it doesn't exist yet.
//So, here, pausing process 2 will force process 3 to continue.
//Process 3 will send a signal back to process 2.
P3.open("P3.txt"); //.try to open P3.txt again
}else //else.
cout << "Process 2: P3.txt opened successfully.\n"; //.tell user that P3.txt opened successfully
P3 >> temp; //read PID from P3.txt
process3 = atoi(temp.c_str()); //convert process 3's PID to an int and store in a pid_t
cout << "Process 2: Read " << process3 << " from P3.txt\n"; //tell user what process 3's ID is
P3.close(); //close P3
//Signal to process 1 that processes 2 and 3 are ready
if(kill(process1, SIGCONT) == -1) //send SIGCONT to process 1
cerr << "Process 2: Failed to send the SIGCONT signal to process 1.\n"; //
else //
cout << "Process 2: Successfully sent the SIGCONT signal to process 1.\n"; //
cout << "Process 2: Paused...\n"; //tell user that process 2 is pausing
pause(); //pause process 2
//Here, process 1 will read process 2's ID then signal back to process 2.
if(kill(process3, SIGCONT) == -1) //send SIGCONT to process 3
cerr << "Process 2: Failed to send the SIGCONT signal to process 3.\n"; //
else //
cout << "Process 2: Successfully sent the SIGCONT signal to process 3.\n"; //
cout << "Process 2: Paused...\n"; //tell user that process 2 is pausing
pause(); //pause process 2
//Here, process 3 will define more signal handlers then signal back to process 2.
if(kill(process1, SIGCONT) == -1) //Send SIGCONT to process 1
cerr << "Process 2: Failed to send the SIGCONT signal to process 1.\n"; //
else //
cout << "Process 2: Successfully sent the SIGCONT signal to process 1.\n"; //
cout << "Process 2: Paused...\n"; //
pause(); //pause process 2
//Here, process 1 will read the first char in the message and signal back to process 2.
cout << "Process 2: Beginning the while loop.\n"; //tell user that the while loop is beginning
while(1){ //while true.
//Here, process 1 will begin its for loop and send a signal back to process 2.
if(sig_ret == 3){ //.if process 1 sent SIGCONT.
//continue; //..do nothing
}else if (sig_ret == 2){ //.else if process 1 sent SIGINT.
if(kill(process3, SIGINT) == -1) //..send SIGINT to process 3
cerr << "Process 2: Failed to send the SIGINT signal to process 3.\n"; //..
else //..
cout << "Process 2: Successfully sent the SIGINT signal to process 3.\n"; //..
cout << "Process 2: Ending while loop.\n"; //..tell user that while loop is ending
pause(); //..pause process 2
//Here, process 3 will break out of its while loop, print its message, signal back to process 2, and terminate.
break; //..break out of while loop
}else if(sig_ret == 0){ //.else if process 1 sent SIGUSR1.
if(kill(process3, SIGUSR1) == -1) //..send SIGUSR1 to process 3
cerr << "Process 2: Failed to send the SIGUSR1 signal to process 3.\n"; //..
else{ //..
cout << "Process 2: Successfully sent the SIGUSR1 signal to process 3.\n"; //..
cout << "Process 2: Paused...\n"; //..
pause(); //..pause process 2
//Here, process 3 will append '0' to its message then signal back to process 2.
} //.
}else if(sig_ret == 1){ //.else if process 1 sent SIGUSR2.
if(kill(process3, SIGUSR2) == -1) //..send SIGUSR2 to process 3
cerr << "Process 2: Failed to send the SIGUSR2 signal to process 3.\n"; //..
else{ //..
cout << "Process 2: Successfully sent the SIGUSR2 signal to process 3.\n"; //..
cout << "Process 2: Paused...\n"; //..
pause(); //..pause process 2
//Here, process 3 will append '1' to its message then signal back to process 2.
} //.
} //.
if(kill(process1, SIGCONT) == -1) //.send SIGCONT to process 1
cerr << "Process 2: Failed to send the SIGCONT signal to process 1.\n"; //.
else{ //.
cout << "Process 2: Successfully sent the SIGCONT signal to process 1.\n"; //.
cout << "Process 2: Paused...\n"; //.
pause(); //.pause process 2
//Here, process 1 will continue its for loop and signal back to process 2.
} //.
} //
if(kill(process1, SIGCONT) == -1) //send SIGCONT to process 1
cerr << "Process 2: Failed to send the SIGCONT signal to process 1.\n"; //
else //
cout << "Process 2: Successfully sent the SIGCONT signal to process 1.\n"; //
cout << "Process 2: Terminated.\n"; //tell user that process 2 is terminating
return 0; //exit normally
}
/***********************************************/
// Author: Cameron Chrobocinski
// Class: Systems Programming
// Assignment: HW05
/***********************************************/
#include <iostream>
#include <sys/types.h>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string>
#include <vector>
using namespace std;
int sig_ret;
void sig_handler(int signo){
if(signo == SIGCONT){
cout << "Process 3: Received SIGCONT.\n";
sig_ret = 3;
}else if(signo == SIGUSR1){
cout << "Process 3: Received SIGUSR1.\n";
sig_ret = 0;
}else if(signo == SIGUSR2){
cout << "Process 3: Received SIGUSR2.\n";
sig_ret = 1;
}else if(signo == SIGINT){
cout << "Process 3: Received SIGINT.\n";
sig_ret = 2;
}
}
int main(){
//Signal handlers
if(signal(SIGCONT, sig_handler) == SIG_ERR){ //Signal handler for SIGCONT
cerr << "Process 3: Failed to catch SIGINT.\n"; //
}else if(signal(SIGINT, sig_handler) == SIG_ERR){ //Signal handler for SIGINT
cerr << "Process 3: Failed to catch SIGINT.\n"; //
}else if(signal(SIGUSR1, sig_handler) == SIG_ERR){ //Signal handler for SIGUSR1
cerr << "Process 3: Failed to catch SIGUSR1.\n"; //
}else if(signal(SIGUSR2, sig_handler) == SIG_ERR){ //Signal handler for SIGUSR2
cerr << "Process 3: Failed to catch SIGUSR2.\n"; //
}
//Declare variables
pid_t pid; //pid for storing this process's ID
pid = getpid(); //store this process's ID in pid
pid_t process2; //process2 for storing process 2's ID
string temp; //temp for storing various strings
cout << "Process 3: Initiated.\n";
//Save PID to P3.txt
ofstream P3("P3.txt"); //P3 for writing process 3's ID to P3.txt
if(!P3.is_open()){ //if P3 did not open.
cerr << "Process 3: P3.txt failed to open\n"; //.tell user that P3 failed to open
return -1; //.exit with error
}else { //else.
P3 << pid; //.write this process's ID to P3.txt
P3.close(); //.close P3
cout << "Process 3: " << pid << " has been written to file P3.txt\n"; //.tell user what process 3's ID is
} //
//Read PID from P2
ifstream P2("P2.txt"); //P2 for reading from P2.txt
if(!P2.is_open()){ //if opening P2.txt failed.
cerr << "Process 3: Error opening P2.txt.\n"; //.tell user that opening P2.txt failed
cout << "Process 3: Paused...\n"; //.tell user that process 3 is pausing
pause(); //.pause process 2
//The most likely cause of P2.txt not opening is that it doesn't exist yet.
//So, here, pausing process 3 will force process 2 to continue.
//Process 2 will send a signal back to process 3.
P2.open("P2.txt"); //.try to open P2.txt again
}else //else.
cout << "Process 3: P2.txt opened successfully.\n"; //.tell user that P2.txt opened successfully
P2 >> temp; //read PID from P2.txt
process2 = atoi(temp.c_str()); //convert process 2's PID to an int and store in a pid_t
cout << "Process 3: Read " << process2 << " from P2.txt\n"; //tell user what process 2's ID is
P2.close(); //close P2
if(kill(process2, SIGCONT) == -1) //send SIGCONT to process 2
cerr << "Process 3: Failed to send the SIGCONT signal to process 2.\n"; //
else{ //
cout << "Process 3: Successfully sent the SIGCONT signal to process 2.\n"; //
cout << "Process 3: Paused...\n"; //
pause(); //pause process 3
}
//Here, process 2 will read process 3's ID from P3.txt then signal to process 1.
//Then, process 1 will read process 2's ID, then wait for process 2 to start its while loop.
//Then, process 2 will begin its while loop, then signal to process 1.
//Then, process 1 will read the first char from the message and signal to process 2.
//Then, process 2 will signal to process 3.
//Receive message from process 2
vector<char> message; //message for concatenating each char in the message
if(kill(process2, SIGCONT) == -1) //send SIGCONT to process 2
cerr << "Process 3: Failed to send the SIGCONT signal to process 2.\n"; //
else //
cout << "Process 3: Successfully sent the SIGCONT signal to process 2.\n"; //
cout << "Process 3: Paused...\n"; //tell user that process 3 is pausing
pause(); //pause process 3
cout << "Process 3: Beginning the while loop.\n"; //tell user that process 3 is beginning its while loop
while(1){ //while true.
//.
if(sig_ret == 3){ //.if process 2 sent SIGCONT.
continue; //..do nothing
}else if (sig_ret == 2){ //.else if process 2 sent SIGINT.
break; //..break out of while loop
}else if(sig_ret == 0){ //.else if process 2 sent SIGUSR1.
message.push_back('0'); //..append '0' to message
}else if(sig_ret == 1){ //.else if process 2 sent SIGUSR2.
message.push_back('1'); //..append '1' to message
} //.
//.
if(kill(process2, SIGCONT) == -1) //..send SIGCONT to process 2
cerr << "Process 3: Failed to send the SIGCONT signal to process 2.\n"; //..
else{ //..
cout << "Process 3: Successfully sent the SIGCONT signal to process 2.\n"; //..
cout << "Process 3: Paused...\n"; //..
pause(); //..pause process 3
//Here, process 2 will signal to process 1.
//Then, process 1 will read the next character in the message then signal to process 2.
//Then, process 2 will signal to process 3.
}
}
//Tell user what the message was
cout << "Process 3: Message received is ";
for(int i = 0; i < message.size(); i++){
cout << message[i];
}
cout << endl;
if(kill(process2, SIGCONT) == -1) //send SIGCONT to process 2
cerr << "Process 3: Failed to send the SIGCONT signal to process 2.\n"; //
else //
cout << "Process 3: Successfully sent the SIGCONT signal to process 2.\n"; //
cout << "Process 3: Terminated.\n"; //tell user that process 3 is terminating
return 0; //exit normally
return 0;
}
Author: Cameron Chrobocinski
Class: Systems Programming
Assignment: HW05
*This folder contains the contents of my submission: this readme.txt, a makefile, message.txt, process1.cpp, process2.cpp, and process3.cpp.
*When compiling the assignment for execution, three executable files will be produced, one for each .cpp file.
*HOWEVER, the only file necessary to execute is process1, it will handle creating separate processes for the other executable files.
*So, just to make sure there are no issues with compilation/execution, there are only 2 commands necessary to run the program: "make" and "./process1",
in that order.
*Process 1 printing its sent message, followed by process 3 printing its received message, then all 3 programs terminating is the ideal exit case.