Ok , let me continue last passage with Semaphore . Semaphore is used in many systems to help processes working
with each other in more effictive way . In order to use Semaphore , you need to initialize it with integer to indicate
what kind of functionality you are going to use . In Linux , you need to create a semaphore with semget() function .
Use semctl() function to set the initial value of the semaphore . And semop() function to perform operation P or
operation V . Here goes my class (semaphore.h):
#include<iostream>
#include <unistd.h>
#include <sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
class Semaphore{
public:
/*initilize with key and value of semaphore*/
Semaphore(const int key,const int value);
const int set_semValue(/*const int value*/);
const int get_semValue();
void del_semValue();
const int semaphore_p();
const int semaphore_v();
private:
union semun sem_union;
int key;
int sem_id;
};
Semaphore::Semaphore(const int key,const int value)
// (sem_union.val)(value),
//this->key(key)
{
this->key = key;
sem_union.val=value;
/*create or open a semaphore ,with permission rw-rw-rw- */
sem_id = semget((key_t)key,1,0666 | IPC_CREAT);
if(sem_id <= 0){
printf("Error while create semaphore\nError code=%d\n",errno);
exit(0);
}
set_semValue();
}
const int Semaphore:: set_semValue(/*const int value*/)
{
/*operate the first(index is 0) semaphore */
if(semctl(sem_id,0,SETVAL,sem_union.val) == -1){
printf("Failed to set value to semaphore\nError code=%d\n",errno);
return 0;
}
return 1;
}
const int Semaphore:: get_semValue()
{
return this->sem_union.val;
}
void Semaphore::del_semValue()
{
if(semctl(sem_id,0,IPC_RMID,sem_union.val) == -1){
printf("Failed to delete semaphore\nError code=%d\n",errno);
}else{
printf("Delete semaphore successfully\n");
}
}
const int Semaphore:: semaphore_p()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = -1; //P()
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1) == -1){
printf("Operation P failed with erro code=%d\n",errno);
return 0;
}
return 1;
}
const int Semaphore::semaphore_v()
{
struct sembuf sem_b;
sem_b.sem_num = 0;
sem_b.sem_op = 1; //V()
sem_b.sem_flg = SEM_UNDO;
if(semop(sem_id,&sem_b,1) == -1){
printf("Operation V failed with erro code=%d\n",errno);
return 0;
}
return 1;
}
Even though this class is very simple and contains a few functions. It works perfectly in my task assgined by the
teacher . So , if you are going to use my class to control threads or processes . You need to create the objects first:
avail=new Semaphore(9876/*key*/,numberOfResource);
full =new Semaphore(5432/*key*/,0);
Well , piece of codes can not explain what they do exactly . So , maybe I post all codes ? (multi_thread.c)
#include"pipe.h"
#include"semaphore.h"
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h>
#include<termio.h>
#include<pthread.h>
#include<errno.h>
#include<string.h>
#define numberOfResource 3
pthread_mutex_t mutex/*=PTHREAD_MUTEX_INITIALIZER*/;
pthread_mutexattr_t mutexAttr;
Semaphore *avail,*full;
void * producer(void *arg)
{
//printf("1");
self_pipe my_pipe("multi_pipe",2);
char buf[]="write to pipe \0";
int ret;
int len=strlen(buf);
int byteWrite;
while(1){
//sleep(5);
//
avail->semaphore_p();
printf("In thread 1 buf string is : %s\n",buf);
ret=pthread_mutex_trylock(&mutex);
if(ret ==0/*!= EBUSY*/)
{
byteWrite= my_pipe.Pwrite(buf,len);
if(byteWrite > 0)
printf("write %d bytes to pipe\n",byteWrite);
else
printf("nothing write to pipe code=%d\n",errno);
full->semaphore_v();
if(pthread_mutex_unlock(&mutex) == 0)
printf("thread 1 released the mutex\n");
else
printf("thread 1 failed to release the mutex\n");
}
else
{
printf("thread1 can not lock mutex\nError code=%d\n",ret);
}
sleep(3);
}
}
void * customer(void *arg)
{
self_pipe my_pipe("multi_pipe",1);
const char *buf;
int ret;
while(1){
//sleep(3);
for(int i=0;i<numberOfResource;i++)
full->semaphore_p();
printf("In thread 2\n");
ret=pthread_mutex_trylock(&mutex);
//printf("thraed 2 tring to use pipe\n");
if(ret != EBUSY)
{
//printf("thread 2 got mutex\n");
buf=my_pipe.Pread();
//printf("thread 2 read completed\n");
if( buf != 0)
printf("read from pipe:%s\n",buf);
else
printf("nothing read from pipe\n");
for(int i=0;i<numberOfResource;i++)
avail->semaphore_v();
if(pthread_mutex_unlock(&mutex) == 0)
printf("thread 2 released mutex\n");
else
printf("thread 2 failed to release mutex\n");
}
else
{
printf("thread2 can not lock mutex");
}
sleep(3);
}
}
int scanKeyboard()
{
int in;
struct termios new_settings;
struct termios stored_settings;
tcgetattr(0,&stored_settings);
new_settings = stored_settings;
new_settings.c_lflag &= (~ICANON);
new_settings.c_cc[VTIME] = 0;
tcgetattr(0,&stored_settings);
new_settings.c_cc[VMIN] = 1;
tcsetattr(0,TCSANOW,&new_settings);
in = getchar();
tcsetattr(0,TCSANOW,&stored_settings);
return in;
}
void * keyboardListener(void *arg)
{
char x=0;
while(1){
x=scanKeyboard();
//get ESC from user , exit process immediately
if(x == 27)
exit(0);
}
}
int main()
{
//pthread_t t1,t2,;
//init the mutex's attribution to PTHREAD_MUTEX_ERRORCHECK
pthread_mutexattr_init(&mutexAttr);
pthread_mutexattr_settype(&mutexAttr,PTHREAD_MUTEX_ERRORCHECK);
//init the mutex with the initilized attribution variable
if(pthread_mutex_init(&mutex,&mutexAttr)==0)
{
pthread_t t1,t2,tKey;
avail=new Semaphore(9876,numberOfResource);
full =new Semaphore(5432,0);
pthread_create(&tKey,NULL,&keyboardListener,NULL);
pthread_create(&t1,NULL,&producer,NULL);
pthread_create(&t2,NULL,&customer,NULL);
printf("two threads have been created\n");
pthread_join(t1,NULL);
pthread_join(t2,NULL);
pthread_join(tKey,NULL);
//destroy the mutex and its attribution variable on exit
pthread_mutexattr_destroy(&mutexAttr);
pthread_mutex_destroy(&mutex);
}
else
{
printf("Init mutex failed !Error code=%d\n",errno);
}
return 0;
}
Ok , with previous pipe.h and semaphore.h files , you can compile my little task and run it successfully , hopefully .
It's not a very difficult task , but it still took much of my time . All right , I got to admit that I am a poor programmer.
This is me , weak and hopeless .
I felt so tired cause I played too much game today . Damn it .
Dormitory is the grave of college students , right ?
Faded to black .