Thursday 20 August 2015

race around

A semaphore is a protected variable whose value can be accessed and altered only by the operations P and V and initialization operation called 'Semaphoiinitislize'.

Binary Semaphores can assume only the value 0 or the value 1 counting semaphores also called general semaphores can assume only nonnegative values.


The P (or wait or sleep or down) operation on semaphores S, written as P(S) or wait (S), operates as follows:

P(S):   IF   S  >  0
                 THEN  S :=  S - 1
                 ELSE   (wait on S)


The V (or signal or wakeup or up) operation on semaphore S, written as V(S) or signal (S), operates as follows:

V(S):   IF  (one or more process are waiting on S)
                THEN (let one of these processes proceed)
                ELSE   S := S +1


Operations P and V are done as single, indivisible, atomic action. It is guaranteed that once a semaphore operations has stared, no other process can access the semaphore until operation has completed. Mutual exclusion on the semaphore, S, is enforced within P(S) and V(S).

If several processes attempt a P(S) simultaneously, only process will be allowed to proceed. The other processes will be kept waiting, but the implementation of P and V guarantees that processes will not suffer indefinite postponement.

Semaphores solve the lost-wakeup problem.

Producer-Consumer Problem Using Semaphores

The Solution to producer-consumer problem uses three semaphores, namely, full, empty and mutex.

The semaphore 'full' is used for counting the number of slots in the buffer that are full. The 'empty' for counting the number of slots that are empty and semaphore 'mutex' to make sure that the producer and consumer do not access modifiable shared section of the buffer simultaneously.

Initialization

Set full buffer slots to 0.
    i.e., semaphore Full = 0.
Set empty buffer slots to N.
    i.e., semaphore empty = N.
For control access to critical section set mutex to 1.
    i.e., semaphore mutex = 1.
Producer ( ) 
WHILE (true)         
            produce-Item ( );
        P (empty);
        P (mutex);
        enter-Item ( )
        V (mutex)
        V (full);

Consumer ( )
WHILE (true) 
        P (full)
        P (mutex);
        remove-Item ( );
        V (mutex);
        V (empty);
        consume-Item (Item)

An Example:-

#include<sys/types.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<unistd.h>
#include<sys/sem.h>

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[10];    /* message data */
           };



union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

struct buffer
{
 unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */
};



int main(int argc, char* argv[])
{
struct msgbuf buf;
struct buffer buf1;
union semun sem;
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL);
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}


////////////////////

int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL);

if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=1;
//semctl(sem_id,0,SETVAL,sem);
sem.val=0;
semctl(sem_id,0,SETVAL,sem);

///////////////////////////


buf.mtype=atoi(argv[1]);
strcpy(buf.mtext,"test it");
int ret=msgsnd(msg_id,&buf,sizeof(buf.mtext),0);

if(ret<=0)
printf("msg sndng error%d\n",ret);

return 0;
}


Creating Reader 1


#include<sys/types.h>
#include<stdio.h>
#include<sys/ipc.h>
#include<unistd.h>
#include<sys/sem.h>

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[10];    /* message data */
           };





union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

struct buffer
{
 unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */
};


int main()
{
struct buffer buf1;
union semun sem;

struct msgbuf buf;
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL);
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}


int ret=msgrcv(msg_id,&buf,sizeof(buf.mtext),10,0);

if(ret<=0)
printf("msg sndng error\n");
else
printf("%s\n",buf.mtext);


int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL);

if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=1;
//semctl(sem_id,0,SETVAL,sem);
buf1.sem_num=0;
buf1.sem_flg=SEM_UNDO;
buf1.sem_op=1;

semop(sem_id,&buf1,1);

return 0;
}


Creating Reader 2


#include<sys/types.h>
#include<stdio.h>
#include<sys/sem.h>
#include<sys/ipc.h>
#include<unistd.h>

struct msgbuf {
               long mtype;       /* message type, must be > 0 */
               char mtext[10];    /* message data */
           };



union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

struct buffer
{
 unsigned short sem_num;  /* semaphore number */
           short          sem_op;   /* semaphore operation */
           short          sem_flg;  /* operation flags */
};


int main()
{
struct msgbuf buf; //buffer for message queue
struct buffer buf1; //buffer for semaphore
union semun sem; //union for semaphore
int msg_id=msgget((key_t)2341,IPC_CREAT|IPC_EXCL);  //taking the message queue
int sem_id=semget((key_t)6001,1,IPC_CREAT|IPC_EXCL); //taking the semaphore

if(sem_id<0)
{
printf("already used semaphore\n");
sem_id=semget((key_t)6001,1,0666);
if(sem_id<0)
{
printf("error in getting semaphore\n");
return 0;
}
}
//sem.val=0;        //initialize the semaphore
//semctl(sem_id,0,SETVAL,sem);
buf1.sem_num=0;
buf1.sem_flg=SEM_UNDO;
buf1.sem_op=-1;  //wait operation

semop(sem_id,&buf1,1); //wait
if(msg_id<0)
{
printf("Already exists\n");
msg_id=msgget((key_t)2341,0666);
if(msg_id<0)
{
printf("handle error\n");
return 0;
}
}

int ret=msgrcv(msg_id,&buf,sizeof(buf.mtext),30,0);  //reading the MQ

if(ret<=0)
{
printf("msg sndng error\n");
}
else
{
printf("%s\n",buf.mtext);
msgctl(msg_id,IPC_RMID,NULL);  //removing the MQ
semctl(sem_id,0,IPC_RMID);     //removing the semaphore
}
return 0;
}

#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
#include<unistd.h>
#include<stdlib.h>

sem_t sem1;


int i=5,res=0;
void * fun1(void* p)
{

sem_wait(&sem1); printf("thread 1 is running:\n"); i=0;
}

void * fun2(void* p)
{
printf("thread 2 is running:\n"); res=200/i; sem_post(&sem1);
}


int main()
{
sem_init(&sem1,0,0); int ret; void *status; pthread_t p_id,t_id; pthread_create(&p_id,NULL,fun1,NULL); pthread_create(&t_id,NULL,fun2,NULL); //printf("%d",i); pthread_join(p_id,&status);

// printf("thread1:%s\n",(char*)status);
pthread_join(t_id,&status);
// printf("thread1:%s",(char*)status);

return 0;
}

Producer Consumer Problem with pthreads using semaphores

PC

Producer Consumer Problem with pthreads using semaphores

 The “Producer-Consumer problem” is one of the best ways to make an example of issues found in Process Communication. To make a simple analogy of the problem , let’s consider a restaurant , with a client who eats what is served for him on the table and a cook that brings food to the table. The issue is that we want to avoid two unpleasant situations. First the cook might bring food to the table when the table is full and then it might fall off. Second we want to avoid the client trying to eat the table , because there is no food on it.
            In reality, the cook is a process known as a “producer” while the client is a process known as the “cosnumer”, the food is data, and the table is a buffer. The problem is also reffered to as the “bounded buffer problem” as we have a limited size buffer that must be shared by two processes (maybe part of the same program) that both add and remove data from it.

The Issue:-


The main issue in this situation has been discussed above, the producer needs room in the buffer to add data, while the consumer needs tha buffer to be non-empty. 

Solutions:-

1. Sleep-wakeup (also known as the inadequate soluiton)
The main ideea of this solution is to use a variable, counter, to count the elements stored in the buffer. To prevent overflows, the code checks if the buffer hasn’t reached maximum capacity. If the value of counter = N (where N=max) , the producer makes a system call, sleep() , to wait until at least one element is ‘consumed’ . If the buffer was empty , the producer notifyes the consumer of the existence of one element in the buffer (namely the one it just added). The consumer code functions on the same principle, it checks if it there is an element to consume, and if the buffer was full and its cycle freed up a position it notifyes the producer. It uses the sleep() system call to wait for an element to be added tot the buffer.

int itemCount

procedure producer() {
    while (true) {
        item = produceItem()

        if (itemCount == BUFFER_SIZE) {
            sleep()
        }

        putItemIntoBuffer(item)
        itemCount = itemCount + 1
       
        if (itemCount == 1) {
            wakeup(consumer)
        }
    }
}

procedure consumer() {
    while (true) {

        if (itemCount == 0) {
            sleep()
        }
       
        item = removeItemFromBuffer()
        itemCount = itemCount - 1
        
        if (itemCount == BUFFER_SIZE - 1) {
            wakeup(producer)
        }
       
        consumeItem(item)
    }
}

2. Semaphor

Using semaphors we can solve this problem better . In the solution below we use two semaphores, full and empty, to solve the problem. Full is incremented and empty decremented when a new item has been put into the buffer. This works great for only one producer and consumer.Given the following circumstances we may encounter and unsatisfactory solution:

Two producers decrement the semaphor empty.One of the prodecers dtermines the next empty slot in the buffer. The sencond producer determines the next empty slot and gets the same result as the first producer. Both producer write in the same spot.
semaphore full = 0
semaphore empty = BUFFER_SIZE

procedure producer() {
    while (true) {
        item = produceItem()
        down(empty)
        putItemIntoBuffer(item)
        up(full)
    }
 }

procedure consumer() {
    while (true) {
        down(full)
        item = removeItemFromBuffer()
        up(empty)
        consumeItem(item)
    }
}

3. Mutex
To solve this issue, we should create a new semaphory to solve the mutual exclusion problem (no more than one producer has access to the buffer at one given time.) , thus the variable semaphory is named “mutex”.

When a process wants to enter critical region , it uses the mutex_lock() to lock the the variable mutex. If mutex is locked it waits it’s turn. The mutex solution works well because it offers another processes to accesss the processor , simply because it avoids the busy waiting solution.

semaphore mutex = 1
semaphore full = 0
semaphore empty = BUFFER_SIZE

procedure producer() {
    while (true) {
        item = produceItem()
        down(empty)
        down(mutex)
        putItemIntoBuffer(item)
        up(mutex)
        up(full)
    }
 }

procedure consumer() {
    while (true) {
        down(full)
        down(mutex)
        item = removeItemFromBuffer()
        up(mutex)
        up(empty)
        consumeItem(item)
    }
}

4. Monitors
A solution to this problem is implementing monitors. A monitor is a collection of data , procedure , variables and data structures grouped into a packed/module. Although processes can always call a monitor’s procedures they DO NOT have access to a monitor’s internal structure. Monitors use a conditional variable , and perform two operations upon it : wait and signal .
            If a proccess can’t continue , a wait operation on the conditional variable blocks the current process. A signal will make it resume operation.
Since mutual exclusion is implicit with monitors, no extra effort is necessary to protect critical section. Monitors provide a kind of high-level synchronization.

monitor ProducerConsumer {
   
    int itemCount
    condition full
    condition empty
   
    procedure add(item) {
        while (itemCount == BUFFER_SIZE) {
            wait(full)
        }
       
        putItemIntoBuffer(item)
        itemCount = itemCount + 1
       
        if (itemCount == 1) {
            notify(empty)
        }
    }
   
    procedure remove() {
        while (itemCount == 0) {
            wait(empty)
        }
       
        item = removeItemFromBuffer()
        itemCount = itemCount - 1
       
        if (itemCount == BUFFER_SIZE - 1) {
            notify(full)
        }
       
        return item;
    }
}

procedure producer() {
    while (true) {
        item = produceItem()
        ProducerConsumer.add(item)
    }
}

procedure consumer() {
    while (true) {
        item = ProducerConsumer.remove()
        consumeItem(item)
    }
}
l_ lass=MsoNormal> 

        if (itemCount == 0) {
            sleep()
        }
       
        item = removeItemFromBuffer()
        itemCount = itemCount - 1
        
        if (itemCount == BUFFER_SIZE - 1) {
            wakeup(producer)
        }
       
        consumeItem(item)
    }
}




            The “Producer-Consumer problem” is one of the best ways to make an example of issues found in Process Communication. To make a simple analogy of the problem , let’s consider a restaurant , with a client who eats what is served for him on the table and a cook that brings food to the table. The issue is that we want to avoid two unpleasant situations. First the cook might bring food to the table when the table is full and then it might fall off. Second we want to avoid the client trying to eat the table , because there is no food on it.

            In reality, the cook is a process known as a “producer” while the client is a process known as the “cosnumer”, the food is data, and the table is a buffer. The problem is also reffered to as the “bounded buffer problem” as we have a limited size buffer that must be shared by two processes (maybe part of the same program) that both add and remove data from it.



5. Messages

Messages sent between proccess is yet another way to solve the producer-consumer problem. We create a special structure , named a mailbox for both processes and messages are sent to these structures rather to memeory address . Thus the program is safer , with a high-end approach.


Usage
            The producer-cosnumer solves the issue of thread synchronization in operating systems, thus making sure there are no problems with stack overflows or inconsistent data addressing.
            Also, another possible application could be in reliable network protocols, to make sure data is delivered reliabley .


An Example:-

#include<stdio.h>
#include<pthread.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<semaphore.h>

sem_t empty,full,mutex;
char buf[10];
void* thread_fun1(void* arg)
{
int i;
//printf("inside producer\n");
for(i=0;i<10;i++)
{
sem_wait(&empty);
sem_wait(&mutex);
buf[i]=i;
printf("item produced is %d\n",buf[i]);
sem_post(&mutex);
sem_post(&full);
sleep(1);

}
pthread_exit("producer\n");

}
void * thread_fun2(void* arg)
{
int j;

printf("inside consumer\n");
for(j=0;j<10;j++)10
{
sem_wait(&full);
sem_wait(&mutex);
      // sleep(1);

j=buf[j];
printf("consumed item is:%d\n",buf[j]);
sem_post(&mutex);
sem_post(&empty);
sleep(5);


}

pthread_exit("consumer\n");
}



int main()
{
pthread_t pid1,pid2;

sem_init(&empty,0,10);
sem_init(&full,0,0);
sem_init(&mutex,1,1);

void *status;
pthread_create(&pid1,NULL,thread_fun1,NULL);
pthread_create(&pid2,NULL,thread_fun2,NULL);


pthread_join(pid1,&status);
printf("the exited status of 1st is %s\n",(char*)status);
pthread_join(pid2,&status);
printf("the exited status %s\n",(char*)status);



return 0;
}

Linux

Linux Socket Programming,

File transfer application using Sockets



 Code for Client


#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>

int main(int argc,int *argv[])
{

char buffer[100];
int fd=open("abc.txt",O_RDONLY);
read(fd,buffer,100);



int sock_id=socket(AF_INET,SOCK_STREAM,0);
if(sock_id<0)
{
printf("Error in getting socket\n");
return 0;
}

struct sockaddr_in clientstruct;
clientstruct.sin_family=AF_INET;
clientstruct.sin_addr.s_addr=inet_addr("127.0.0.1");
clientstruct.sin_port=10125;

int ret=connect(sock_id,(struct sockaddr *)&clientstruct,sizeof(clientstruct));


write(sock_id,buffer,100);

close(sock_id);


return 0;
}

Code for Server

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<fcntl.h>
int main()
{
char buffer[100];
int session_id;
int server_id=socket(AF_INET,SOCK_STREAM,0);
if(server_id<0)
{
printf("Error in getting socket\n");
return 0;
}
struct sockaddr_in serverstruct,clientstruct;
serverstruct.sin_family=AF_INET;
serverstruct.sin_addr.s_addr=inet_addr("127.0.0.1");
serverstruct.sin_port=10125;
int i=bind(server_id,(struct sockaddr*)&serverstruct,sizeof(serverstruct));
if(i<0)
{
printf("Error in bind\n");
return 0;
}
i=listen(server_id,10);
if(i<0)
{
printf("Error in listening\n");
return 0;
}
int client_len=sizeof(serverstruct);
while(1)
{
int fd=open("target.txt",O_WRONLY);
if(fd<0)
{
printf("file cant be iopened\n");
}
printf("Waiting for the client\n");
session_id=accept(server_id,(struct sockaddr*)&serverstruct,&client_len);
read(session_id,buffer,sizeof(buffer));
write(fd,buffer,100);
printf("From CLIENT:%s\n",buffer);
close(fd);
close(session_id);
}
close(server_id);
return 0;
}