Øvelse+12+-+Processes+and+IPC+in+Linux

=Exercise 1 Processes=

Exercise 1.1 Simple process creation
Create a program that, when executed, spawns one child 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 (hint: use getpid).
 * The parent process should output \Hi! I am the parent process", the value returned from fork and the PID of the process.
 * The parent process should wait for the child to die. Note that you have to include the header le sys/wait.h. Use the man pages to get help on the function wait.

Explain the value of the PIDs and the return values from fork - how can one function return two different values?

Explain what happens when a process is forked: code format="cpp"
 * What happens to the memory from the parent passed to the child
 * //The child gets a new PID//
 * //Virtual address space from parent is replicated (duplicates parents page tables)//
 * What is passed to the child process and what is not?
 * //Includes states of mutexes, conditionals etc.//
 * //Includes open file descriptors from parent (a copy)//
 * //Only the thread that calls fork is duplicated in the child//
 * Why must it be exit that is called from within the child and not exit?
 * 1) include 
 * 2) include 
 * 3) include 

//Funktion til afvikling af child void Child(pid_t pid) {   printf ("Hi! I am the child process \n"); //Udskriver value af pid printf ("My value nubmer is: %d\n", (int) pid); //Udskriver vale af getpid printf ("My process nubmer is: %d\n", (int) getpid); }

//Funktion til afvikling af parent void Parent(pid_t pid) {   printf ("Hi! I am the parent process \n"); printf ("My value nubmer is: %d\n", (int) pid); printf ("My process nubmer is: %d\n", (int) getppid); }

int main {   int status; //Opretter variablen af typen pid_t pid_t pid;

// fork retunere 2 værdiere, childen værdien er 0, og parent er != 0. // Efter en fork bliver programmet dublikeret pid = fork;

if (pid != 0) {       wait(&status); Parent(pid); }   else {       Child(pid); _exit(1); } } code

Exercise 1.2 Single program - multiple processes
Repeat the above but having 3 separate programs instead of one.
 * Program 1 should spawn programs 2 & 3.
 * Program 2 should output \tick" every second for 5 seconds.
 * Program 3 should output \tock" every second for 8 seconds.
 * The parent program should wait for both child processes to nish. Then it should output \Done."

Explain what happens when a process is spawned via the exec function familily: code format="cpp"
 * What is passed to the \child" process and what is not?
 * //Not//
 * //Memory Map//
 * //Memory Locks//
 * //Shared Memory//
 * //Is//
 * //Open files remain open//
 * What should one be vary about when spawning processes in a security context (in relation to the previous question)?
 * //We must remember to delete//
 * 1) include 
 * 2) include 
 * 3) include 
 * 4) include 

void Child1(void) {   for (int i = 1; i != 5; i++) {       printf("tick \n");

sleep(1); } }

void Child2(void) {   for (int i = 1; i != 8; i++) {       printf("tock \n");

sleep(1); } }

void Parent(void) {   printf ("DONE ! \n"); }

int main {   int status; pid_t pid;

pid = fork;

if (pid == 0) {       Child1; _exit(1); }   pid = fork; if (pid == 0) {       Child2; _exit(1); }   else {       wait(&status); wait(&status);

Parent;

return 0; } } code =Exercise 2 Shared Memory=

The basic idea is to create 3 programs as shown in fi gure 2.1. The main program is tasked with setting op shared memory, hereby also creating a mutex and a conditional variable in shared memory1. Having done this two child program must be spawned.

The fi rst program, Input, must wait on input2 from stdin place it in shared memory and signal the conditional variable.

The second program, Output, must wait on the aforementioned conditional variable and once signaled retrieve the read string from shared memory and print out via stdout.

Questions to answer:
 * Describe the concept behind shared memory this includes which steps to go through and what to remember from a purely functional point of view.
 * //First: Create and attach to SHM//
 * //Second: Read or write SHM//
 * //Thrid: Clean up//
 * Under which circumstances would you consider shared memory a viable solution?
 * //If you have 2 application, there must talk together, shared memory is a solution//
 * //it could be a server/client system//
 * Consider a scenario where two programs communicate via shared memory and program
 * B has taken a mutex that program A also waits for. In this unfortunate moment program
 * B crash whilst having acquired said mutex.
 * What is the problem?
 * //If program B crash when it have the mutex, we end in a dead lock//

code format="cpp"
 * 1) include 
 * 2) include
 * 3) include 
 * 4) include 
 * 5) include 
 * 6) include 
 * 7) include 
 * 8) include 
 * 9) include 
 * 10) include 

struct SHARED {	int data_; pthread_mutex_t shared_mutex; //Placed in shared memory pthread_mutex_t shared_mutex_cond; pthread_cond_t shared_condvar; bool exit_; };

void Input(SHARED* shm) {	int in;

while(shm->exit_ == false) {

pthread_mutex_lock(&shm->shared_mutex); std::cout << "Input: "; std::cin >> in;

if(in == 0) {			shm->exit_ = true; shm->data_ = 0; }		else shm->data_ = in; std::cout << std::endl << std::endl; pthread_cond_signal(&shm->shared_condvar); pthread_mutex_unlock(&shm->shared_mutex);

//Can be useful sleep(1); } }

void Output(SHARED* shm) {	while(shm->exit_ == false) {		pthread_cond_wait(&shm->shared_condvar, &shm->shared_mutex_cond); pthread_mutex_lock(&shm->shared_mutex); if(shm->data_ != 0) std::cout << "Output: " << shm->data_ << std::endl; pthread_mutex_unlock(&shm->shared_mutex); } }

void FORK(SHARED* shm) {  if(fork == 0) //Fork the input {		while(shm->exit_ == false) {			if(fork == 0)//Fork the input {				Input(shm); _exit(0); //Terminate the current process }			wait(0); }		_exit(0); }

if(fork == 0) //Fork the collector {		while(shm->exit_ == false) {			if(fork == 0) //Fork the collector {				Output(shm); _exit(0); //Terminate the current process }			wait(0); }		_exit(0); }

//Wait for kids wait(0); wait(0); }

int main {   // Create const unsigned int SHM_KEY(5070); int shmId = shmget(SHM_KEY, sizeof(SHARED), IPC_CREAT | 0666);

// Attach SHARED* shm = reinterpret_cast<SHARED*>(shmat(shmId,0,0)); if(shm == reinterpret_cast<SHARED*>(-1)) {	   std::cout << "SHARED cast fejl" << std::endl; _exit(1); }

//Init shm->data_ = 0;

shm->exit_ = false;

pthread_mutexattr_t mutex_attr; pthread_mutexattr_init(&mutex_attr); pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&shm->shared_mutex, &mutex_attr);

pthread_mutexattr_t mutex_attr_cond; pthread_mutexattr_init(&mutex_attr_cond); pthread_mutexattr_setpshared(&mutex_attr_cond, PTHREAD_PROCESS_SHARED); pthread_mutex_init(&shm->shared_mutex_cond, &mutex_attr_cond);

pthread_condattr_t cond_attr; pthread_condattr_init(&cond_attr); pthread_condattr_setpshared(&cond_attr, PTHREAD_PROCESS_SHARED); pthread_cond_init(&shm->shared_condvar, &cond_attr);

//Fork FORK(shm);

//Clean up 	shmdt(shm); shmctl(shmId, IPC_RMID, 0);

return 0; } code