I3MUP1+Exercise+XXX

toc =Exercise XXX= //In this exercise you will use the process creation primitives fork, wait, _exit and execv to create// //a command line interpreter (CLI). Through this, you will gain an understanding of the process concept and// //the difference between a process and the program it executes.//

Exercise XXX.1
Create a program that, when executed, spawns one child process. fork and the PID of the process.
 * The child process should output “Hi! I am the child process”, the value returned from fork
 * and the Process ID (PID) of the process
 * The parent process should output “Hi! I am the parent process”, the value returned from

The program was written by simply forking a process, and checking whether the process is child or parent and outputting the process id and the value returned from fork. When running the program we see that the parent process fork call returns the process ID of the child process. And that the child process fork return value, as expected is 0.

The code to the program is shown below:

code format="cpp" int main {   pid_t pid1;

pid1 = fork;

if(pid1 == 0) cout << "Hi, I'm a child process! Fork Value: " << pid1 << " Process ID : " << " " << getpid << endl;

else if(pid1 == -1) cout << "Forking Failed!\n"; else cout << "Hi I'm a parent process! FORK Value : " << pid1 << " Process ID : " << " " << getpid << endl; return 0; } code

Exercise XXX.2
//Create a program that, when executed, spawns 2 child processes.//
 * Child process 1 should output “tick” every second for 5 seconds
 * Child process 2 should output “tock” every second for 8 seconds
 * The parent process should wait for both child processes to finish. Then it should output “Done.”

The program below starts out by forking the process and then checks whether the process id is 0(Which would mean that it is a child process). If the process is a child process the program outputs "Tick #" and if it isn't it forks the process again creating another child process. We once again check whether the process is parent or child. If it's a child we output "Tock #" and if parent waits for both child processes to finish before outputting "Done."

code format="cpp" using namespace std;

int main {   pid_t pid1; pid_t pid2; int status1, status2;

pid1 = fork;

if(pid1 == 0) {       for(int i = 0; i <=     5; i++) {           sleep(1); cout << "Tick #" << i << endl; }       _exit(1); }   else {       pid2 = fork; if(pid2 == 0) {           for(int i = 0; i<=8; i++) {               sleep(1); cout << "Tock #" << i << endl; }           _exit(1); }       else {           wait(&status1); wait(&status2); cout << "Done!\n"; }   } } code

Exercise XXX.3
//Create a program that, when executed, prompts the user for a command to execute and then spawns a process which executes it (use execv to execute the command). All commands are assumed to be in the directory /bin.//

For this exercise, we were handed implementations of main and a function to tokenize a string. The only function we had to implement was executeCommand. Our code is shown below.

We create an array of arguments to be used by the execv function call. The first element in this array is the path of the program to be run by the child process, and the other elements are command line arguments passed to the program. An STL vector is used to hold the tokenized user input. The first element in the argument array is filled 'manually' by adding "/bin/" to the first command input by the user. We convert from string type to char * by using the c_str function and then typecast to char *. The remaining commands are copied into the argument list in a for loop, and we make sure to null-terminate the array afterwards. fork is used to spawn a child process, and execv makes the child process execute the command given by the user. code format="cpp" void executeCommand(string cmd) {	vector commands = tokenize(cmd); int numOfCmds = commands.size; char ** exec_args = new char *[numOfCmds + 1]; exec_args[0] = (char *)("/bin/" + commands[0]).c_str;

for (int i = 1; i < numOfCmds; i++) {		exec_args[i] = (char *)commands[i].c_str; }	exec_args[numOfCmds] = NULL;

int status; pid_t pid = fork;

if(pid == 0) {		execv(exec_args[0], exec_args); cout << cmd << " is an unknown command!\n"; _exit(1); }	else {		wait(&status); }	delete [] exec_args; } code

Program execution example: