Part1: What
is the difference between Single Process (program),
Mutliprocesing and Mutlithreading?
To illustrate the
difference we will consider an example.
#include <stdio.h>
#include <stdlib.h>
void first_function(int *);
void second_function(int *);
void final_function(int , int);
int i =0, j =0;
main()
{
first_function(&i);
second_function(&j);
final_function(i,j);
}
void first_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the first_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void second_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the second_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void final_function(int first, int second)
{
int final_score;
final_score = first + second ;
printf("In final : first = %d, second = %d and final_score = %d\n",
first, second, final_score);
}
|
The figure below shows the layout of this program in the
virtual address memory. The various memory areas are
- A read-only memory for the machine language instructions
of the program
- A read-write area for the global variables
- A heap area for memory that is dynamically allocated
(example malloc calls)
- A stack on which local variables of current functions
are maintained
Unix
Multiprocessing:
We can rebuild the first program to illustrate the unix
mutiprocessing. The main routine starts in a single
process which is the parent process. The parent process
then creates the child process to execute the first_function
and another child process to execute the second_function
routines. Then the parent process waits for both of its child
process to finish and then calls final function .
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
void first_function(int *);
void second_function(int *);
void final_function(int,int);
int shared_mem_id;
int *shared_mem_ptr;
int *i, *j;
main()
{
pid_t child1_pid, child2_pid;
int state;
/* initialise the shared memmory segment */
shared_mem_id = shmget(IPC_PRIVATE, 2*sizeof(int),0);
shared_mem_ptr = (int *)shmat(shared_mem_id, (void*)0, 0);
/* giving the pointers to the variables */
i = shared_mem_ptr;
j = (shared_mem_ptr + 1);
*i = 0;
*j =0;
/* start the first child process */
if((child1_pid = fork())== 0)
{
/* job of first child*/
first_function();
exit();
}
/*start the second child process*/
if((child2_pid = fork())== 0)
{
/* job of second child*/
second_function();
exit();
}
/*parent*/
waitpid(child1_pid, state,0);
waitpid(child2_pid, state,0);
final_function(*i, *j);
}
void first_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the first_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void second_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the second_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void final_function(int first, int second)
{
int final_score;
final_score = first + second ;
printf("In final : first = %d, second = %d and final_score = %d\n",
first, second, final_score);
}
|
the UNIX system calls
that create a new process is called fork. the fork
creates the child process that is identical to its parent
process at the time of function call of fork .
following are the result
- The child has its own process identifier, or PID
- the fork call returns different values to child and
parent processes (returns a value of 0 to child and
child's PID to parent)
As depicted in the figure, as soon as the program forks into
two different processes, the parent and child process execute
independently unless there is synchronization.
Pthreads
Concurrent Programming:
Pthreads
is a standardized model for dividing a program into subtasks
which can be run in parallel. We will repeat the example using
Pthreads. The program starts with the main thread. Using the
Pthread function calls, the creator thread spawns a thread to
execute the first_function and another to execute the
second_function routine.
#include <pthread.h>
void first_function(int *);
void second_function(int *);
void final_function(int,int);
int i=0; j=0;
main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, (void*) first_function, (void*)&i);
pthread_create(&thread2, NULL, (void*) second_function, (void*)&j);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
final_function(i,j);
}
void first_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the first_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void second_function(int *num)
{
int x,y,z;
for(x=0; x< 10; x++)
{
printf("Inside the second_function\n");
for(y=0; y< 1000; y++)
z =z+1; /* introduce delay*/
(*num)++;
}
}
void final_function(int first, int second)
{
int final_score;
final_score = first + second ;
printf("In final : first = %d, second = %d and final_score = %d\n",
first, second, final_score);
}
|
The pthread_create uses
the following parameters
- A pointer to a buffer which identifies the newly created
thread( Type of pthread_t*).
- A pointer to a structure of type thread attribute
object.
- A pointer to routine at which the new thread will start
executing
- A pointer to a parameter to be passed to the routine at
which the new thread starts
threads are created without replicating an entire process.
|