Semaphore in Linux

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 .

猜你喜欢

转载自blog.csdn.net/cwg2552298/article/details/79830442