Session 6 : Process Types & Management Part II


Processes:Types-Management– II 

Soldier
To General: Sir! A Small Enemy Group Is Attacking.. General: Quickly
Bring Me My Red Shirt.. "After Enemyz Defeat" Soldier: Sir
Why D Red Shirt?? General: In Red Shirt If I Got Shot, My Soldiers
Would'nt See My Blood So They Wont B Discouraged.. Soldier: Sir 100
Enemy Tanks Are Attacking.. General: Hurry Up! Bring Me My Yellow
Trousers.... ;->”

Q?How does the process terminates 
/>The process terminates if it executes the system call exit
/>the child can pass a byte to the parent via wait(argument)
and the parent receives it
/>the OS recovers the resources
used by the child processes via wait


Q?What does fork() do 
/>fork() call makes a near
duplicate of the current process, identical in almost every way(not
everything but close enough). 
The new process(child) gets a different process ID (PID) and has the PID of the process(parent) as its parent PID (PPID).

Q?This two process are now running exactly the same code, but how do we
distinguish between them 
/>the return code of fork()
provides the information about who is child and who is parent. The
child has return code 0.
While the parent gets the PID of
the child. If the fork() fails the parent will get the errorcode. 
Parent knows the pid of the child and can communicate with it , kill it or
wait for it. 
The child can always find its parent by calling a system call getppid().


Example 1: Demonstration of Fork, Wait, and Exit 
/*
fork2. c
Illustrates fork, wait and exit return information
Use: Prompt> fork2
echo $?
Last shell command should print the parent return value (15)
*/

#include <stdio.h>

main() {
int n, status, cpid;

printf("Parent pid = %d\n", getpid());

n = fork();

if (n != 0) {
// parent code
printf ("I'm the parent with PID %d \t fork returned %d \t my parent is %d\n",
getpid(), n, getppid());
status = 0;
sleep(5); // verify status of child
cpid = wait(&status);
printf("I received from my child %d this information %x\n",
cpid, status);
}
else { // child code
printf ("I'm the child with PID %d \t fork returned %d \t my parent is %d\n",
getpid(), n, getppid());
sleep(5);
printf("Child complete\n");
status=123;
exit(4);
}
printf("Parent complete\n");
exit(15);
}
 


Result:


Parent
pid = 10143 
I'm the parent with PID 10143   fork returned 10145   my parent is 10142 
I'm the child with PID 10145   fork returned 0   my parent is 10143 
Child complete 
I received from my child 10145 this information 400 
Parent complete 

Process returned 15 (0xF)  execution time : 20.003 s 
Press ENTER to continue. 

Example 2 : Wait.c 
//If argc > 1
//wait for the end of all its offsprings
//else
//wait for the end of any offspring

#include <signal.h>
// all those signals who handle signal are defined in this header file
int
main (int argc, char ** argv) {

int i, ret, code;

if (argc > 1)
signal(SIGCHLD, SIG_IGN); // ignores the childtermination

for(i=1;i<6;i++)
if (fork() == 0) { // child
sleep (5*i);
printf ("Child %d slept%d seconds\n", getpid(), i*5);
exit(i); // exit with code i
}

sleep (5); // allows some childs to terminate

ret = wait(&code);

printf("Wait: ret = %d code = %x\n", ret, code);

}

Result: 
Child 11096 slept5 seconds 
Child 11097 slept10 seconds 
Wait: ret = 11096 code = 100 

Process returned 29 (0x1D)   execution time : 5.005 s 
Press ENTER to continue. 
Child 11098 slept15 seconds 
Child 11099 slept20 seconds 
Child 11100 slept25 seconds 

Q? what is exec() 
/> Exec() : replaces the program in the current process with a brand new
program. 
The family of exec function are : 
int execl(const char *path, const char *arg, ...);
ex: execl("new_path", argv[0], "any_arg", NULL)

int execlp(const char *file, const char *arg, ...);
ex: execlp("new_file_name", argv[0], "any_arg", NULL)

int execle(const char *path, const char *arg , ..., char * const envp[]);
ex: char *envp[] = {"any_val1", "any_valN", NULL};
execle("new_path", argv[0], "any_arg", NULL, envp)

int execv(const char *path, char *const argv[]);
ex: char *args[] = {"any_val1", "any_valN", NULL};
execv("new_path", args)

int execvp(const char *file, char *const argv[]);
ex: char *args[] = {"any_val1", "any_valN", NULL};
execvp("new_file_name", args)


Example 3: execlp.c
/*

execlp.c

Illustrates the use of system calls system and exec

l in exec is for list: the arguments are passed in a list
p in exec is for PATH: the executable file is searched in the directories listed in PATH

The second argument of exec is the name of the process during its running phase,
it corresponds to argv[0].

*/
#include <stdio.h>
#include <unistd.h>

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

system ("date");

// system ("date") creates a shell process that execute
// command "date" - output goes to screen
// return here

if (execlp ("argv", "myls", "-l", "-R", "/cygdrive/d", (char *) 0) < 0)
printf ("error exec\n");
printf ("listing complete !!!\n"); // NEVER REACHED
exit (0);
}

Result:
Sat Nov 22 19:44:52 CET 2014 
error exec 
listing complete !!! 

Process returned 0 (0x0)   execution time : 0.004 s 
Press ENTER to continue. 

Explanation:

execlp ("argv", "myls", "-l", "-R", "/cygdrive/d", (char *) 0)
"argv" = new file name
"myls" = arg[0]
"-l" = arg[1]
"-R" = arg[2]
"/cygdrive/d" = arg[3]
(char *) 0 = Null

The execlp process reaches : the NEVER REACHED situation then the execlp has failed :
if it do not reach then execlp has been executed correctly.




Example 4: execve.c
/*

execve.c

Illustrates the use of system calls system and exec

v in exec is for variables: the arguments are passed as a sequence of variables
e in exec is for env: the executable file inherits the shell environment variables

*/
// Use of system calls system and exec
// use: execve command arg environment

#include <stdio.h>
#include <unistd.h>

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

char * arguments[10]={"name", "-l", "-R", "/", "\0"};

// strcpy(arguments[0] , "name");

printf("%s\n", envp[0]);// GNOME_KEYRING_PID
system ("date");

// system ("date") creates a shell process that execute
// command "date" - output goes to screen
// return here

// if (execlp ("argv", "name", "-l", "-R", "/" (char *) 0) < 0)
if (execve ("argv", arguments , envp) < 0) { // Notice complete path
printf ("error exec\n");
exit(1);
}
printf ("listing complete !!!\n"); // NEVER REACHED
exit (0);
}


Result:

GNOME_KEYRING_PID=1403
Sat Nov 22 21:00:54 CET 2014 
error exec 

Process returned 1 (0x1)   execution time : 0.023 s 
Press ENTER to continue. 


Q? What are coperating processes 
/> this types of process are affected by the execution of another process.It has following advantages: information sharingcomputation speed-upmodularity– convenience



Q?What is Producer-Consumer Problem 
/>What is happening here is that the producer process produces
information that is consumed
by a consumer process. There are two imporatant possibility for
storage of information produced
by the producer. One is unbounded-buffer
which has no practical limit on the size of the buffer. Another one
is bounded-buffer which has
a limited buffer size. There is a problem is using the
unbounded-buffer solution cos it consumers lot of memory. So we have
a Bounded buffer. How to use this
bounded buffer shared memory in the producer-consumer is known
as producer-consumer problem: Here the real problem is how to make
sure that the producer won't try to add data into the buffer
if it's full and the consumer won't
try to remove data from the empty buffer. 
The solution is defined below : 


#define N 10 //defines max buffer-size
typedef .. Item ;
Item buffer[N];
int in = 0;
int out = 0;

//Producer Process
while(true){ // loop forever
/* produces an item in nextp*/
nextp = produce();
while((in+1)%N == out) // dont use ; here otherwise producing will not start
buffer[in]= nextp; // produce
in = (in+1)%N; // increment counter

}
//Consumer Process
while(true){ // loop forever

while(in==out); // while in == out does nothing
nextc = buffer[out]; // otherwise consumes
out= (out+1)%N; // increment counter
/*consumers the item in nextc*/
nextc = consume(); //consumes
}


Q?what are threads 
/>a thread is a basic unit of CPU
utilization and consist of program
counterregister setstack space
/>a thread share with its peer threads its – code
sectiondata section
and OS resources (task Domain)
/>using multiple thread in a same job results to higher throughput and
higher performance
/>while using multiple thread one main thread is blocked and waiting,
while a second thread of same task can run
/>threads helps to achieve parallelism
in executing process

Q?what are the pros user threads 
/>fast context switching between threads of the same task (no
overhead)
/>can be implemented on top of any kernel

Q?what are the cons of user threads 
/>if a thread performs a blocking system call, all the threads of the
same task are blocked 
/>a single thread per task running even on a multiprocessor system 

Q?what are the pros of kernel thread 
/>the ready threads can be scheduled even if they belong to the task of
a thread that has issued a blocking system call 
/>multiple thread per task can be executed on a multiprocessor system 

Q?what are the cons of kernel thread 
/>more expensive context switiching cos
if needs the passage to kernel mode and kernel support (higher
overhead)
/>constraints on the minimum number of thread per task/system. 

Q?what are pthreads
/>pthreads are a simple and effective way of creating a multi-threaded
application.(p stands for POSIX)
/>basic mechanism priciple is executing two
tasks in parallel and merging back to the single thread when the work
has been done 
/>all c program using pthreads need to include the pthread.h
header file 

Q?what are the steps to create a threaded program 
/>Basically there are 4 steps: 
/1>define thread reference variable: pthread_t thread0;
/2>create entry point for the thread: 
void *my_entry_function(void *param);
/3>create the thread: pthread_create(&thread0,NULL,my_entry-function,
&parameter);
/4>join everything back up: pthread_join(thread0,NULL);

Note:
while compiling the program, you will also need to add -lpthread to
the compile command i.e. : 
gcc
yourprogram.c -o yourprogram -lpthread 

Example 1 : self.c
/* self.c Shows that a process is a a single thread */

#include <stdio.h>
#include "pthread.h" // POSIX threads


int
main (void)
{
pthread_t pt;
pt = pthread_self();

printf("main thread id = %ld\n", pt);
printf("process id = %d\n", getpid());
}

Result:

main thread id = 0 
process   id = 5774 

Process returned 22 (0x16)   execution time : 0.002 s 
Press ENTER to continue. 


Example 2 : creation-and-join.c

/* Creates two threads,
one printing 1000 "a"s, the other printing 1000 "b"s.
Illustrates: thread creation,
thread joining
retcode and retvalue.
*/

#include <stdio.h>
#include <unistd.h>
#include "pthread.h"

//global variable

int glo = 100;

static void *
process (void *arg)
{

char *c = (char *) arg; // cast the void argument to the real type

int i;

fprintf (stderr, "Starting thread %s, glo=%d\n", c, glo);
for (i = 0; i < 1000; i++)
write (1, c, 1);
return c;
}




int
main (void)
{
int retcode;
pthread_t th_a, th_b;
void *retval;

retcode = pthread_create (&th_a, NULL, process, (void *) "a");
if (retcode != 0)
fprintf (stderr, "create a failed %d\n", retcode);
retcode = pthread_create (&th_b, NULL, process, (void *) "b");
if (retcode != 0)
fprintf (stderr, "create b failed %d\n", retcode);
retcode = pthread_join (th_a, &retval);

fprintf(stderr, "retval : %c\n", * (char *) retval);

if (retcode != 0)
fprintf (stderr, "join a failed %d\n", retcode);

retcode = pthread_join (th_b, &retval);

fprintf(stderr, "retval : %c\n", * (char *) retval);

if (retcode != 0)
fprintf (stderr, "join b failed %d\n", retcode);
return 0;
}

Result:
Starting thread a, glo=100
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaretval : a
Starting thread b, glo=100
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbretval : b



Note * : this cannot be compiled in code:blocks compiler becouse we do not have the required posix library in our code.

Steps to how to compile and run this code:
/1> go to the location where you have the code : ex: /Desktop/os/programs
/2> hit command : $ gcc yourProgramName.c -o yourProgramName -lpthread
/3> now new executable file will be generates so execute this file using :
$ ./yourProgramName


Example 3 : try-exit.c
/* try-exit.c
Illustrates pthread_detach and the difference between
exit : ends all its threads
pthread_exit : ends the issuing thread
*/

#include <pthread.h>
#include "errors.h"

int one=1, two=2;

static void *
print_thread (void *arg)
{
int *t = (int *) arg;
int status, i;

status = pthread_detach (pthread_self ()); // parent is not joining
if (status != 0)
err_abort (status, "Detach thread");

for (i = 0; i < 5; i++) {
sleep (1);
system("date");
printf ("Active thread: %d i : %d\n", *t, i);
printf(" Global Variables %d, %d\n", one, two);
}
//exit(0);
return NULL;
}
int main (int argc, char *argv[])
{
int status;
pthread_t thread;
status = pthread_create (&thread, NULL, print_thread, &one);
if (status != 0)
err_abort (status, "Create print thread 1");
status = pthread_create (&thread, NULL, print_thread, &two);
if (status != 0)
err_abort (status, "Create print thread 2");
if (argc > 1){
sleep(4);
pthread_exit(NULL); // ends the main thread, but the two created threads continue running
}
else {
sleep(3);
exit(0); // after 3 seconds ends all threads
}
}


Result:

Sun Nov 23 12:51:08 CET 2014 
Sun Nov 23 12:51:08 CET 2014 
Active thread: 2  i : 0 

Global Variables 1, 2 
Active thread: 1  i : 0 

Global Variables 1, 2 
Sun Nov 23 12:51:09 CET 2014 
Sun Nov 23 12:51:09 CET 2014 
Active thread: 1  i : 1 
Active thread: 2  i : 1 

Global Variables 1, 2 

Global Variables 1, 2 

Example : 4 try-common-memory.c
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int myglobal;

void *
thread_function (void *arg)
{
int *argc = (int *) arg;
int i, j;
for (i = 0; i < 20; i++) {
j = myglobal;
j = j + 1;
printf (".");
fflush (stdout);
if (*argc > 1) // with argc = 1 the thread does not sleep
sleep (1); // and is faster than the main thread
myglobal = j;
}
return NULL;
}

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

pthread_t mythread;
int i;

if (pthread_create (&mythread, NULL, thread_function, &argc)) {
printf ("error creating thread.");
abort ();
}

for (i = 0; i < 20; i++) {
myglobal = myglobal + 1;
printf ("o");
fflush (stdout);
sleep (1);
}

if (pthread_join (mythread, NULL)) {
printf ("error joining thread.");
abort ();
}

printf ("\nmyglobal equals %d\n", myglobal);

exit (0);

}


Result:

o....................ooooooooooooooooooo

myglobal equals 40 


YouTube : 
https://www.youtube.com/watch?v=W2T0zMtNwpc&list=PL2bE7itI_Ia5EalU1kCXtlNxJHAsUjZEB&index=7



Comments

Popular Posts