日期:2014-05-16 浏览次数:20790 次
【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
关于pv操作部分的内容,其实算不上什么新的东西。但是它对于我们理解信号量、消息处理部分的工作还是有很大帮助的。之前我们给出了一个win32的处理方案,但是实现的比较草率。所以我们今天可以利用linux上的信号量函数把这个功能重新实现一遍。
(1)linux下面信号量的基本函数
a)创建信号量 sem_init
b)等待信号量 sem_wait
c)释放信号量 sem_pos
d)删除信号量 sem_destroy
(2)编写pv操作函数
之前在编写pv操作的时候,没有考虑到消息处理的时序问题,所以在某些极端的情况下可能会造成一些问题。所以本次pv操作采用了循环队列的形式,保持了消息的先后入队顺序。这样对于线程收到的各种消息就可以依次进行处理解决了。同样,我们文件编译的方法非常简单,shell下输入gcc sem.c -g -o sem -lpthread即可。
    可能有同学会问,单独的循环队列和pv操作处理上有什么差别?其实差别很简单,pv可以是不同线程向一个线程发送消息,而循环队列只能接受一个线程发送的消息,否则处理上就麻烦了。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
struct MSG
{
	sem_t s_empty;
	sem_t s_full;
	sem_t s_msg;
	int* p_buffer;
	int start;
	int end;
	int count;
};
#define STATUS int
#define TRUE 1
#define FALSE 0
static struct MSG* p_msg = NULL;
struct MSG* alloc_msg(int count)
{
	struct MSG* p_msg;
	p_msg = (struct MSG*) malloc(sizeof(struct MSG));
	if(NULL == p_msg)
	{
		goto error1;
	}
	memset(p_msg, 0, sizeof(struct MSG));	
	p_msg->count = count;
	p_msg->p_buffer = (int*)malloc(sizeof(int)* count);
	if(NULL == p_msg->p_buffer)
	{
		goto error2;
	}
	sem_init(&p_msg->s_empty, 0, count);
	sem_init(&p_msg->s_full, 0, 0);
	sem_init(&p_msg->s_msg, 0, 1);
	return p_msg;
error2:
	free(p_msg);
error1:
	return;
}
void del_msg(struct MSG* p_msg)
{
	if(p_msg)
	{
		if(p_msg->p_buffer)
		{
			free(p_msg->p_buffer);
		}
		
		sem_destroy(&p_msg->s_msg);
		sem_destroy(&p_msg->s_full);
		sem_destroy(&p_msg->s_empty);
		free(p_msg);
	}
}
STATUS put_msg(struct MSG* p_msg, int data)
{
	if(NULL == p_msg )
	{
		return FALSE;
	}
	sem_wait(&p_msg->s_empty);
	sem_wait(&p_msg->s_msg);
	p_msg->p_buffer[p_msg->start] = data;
	p_msg->start = (p_msg->start + 1) % p_msg->count;
	sem_post(&p_msg->s_msg);
	sem_post(&p_msg->s_full);
	return TRUE;
}
STATUS get_msg(struct MSG* p_msg, int* p_buf)
{
	if(NULL == p_msg || NULL == p_buf)
	{
		return FALSE;
	}
	sem_wait(&p_msg->s_full);
	sem_wait(&p_msg->s_msg);
	p_buf[0] = p_msg->p_buffer[p_msg->end];
	p_msg->end = (p_msg->end + 1)% p_msg->count;
	sem_post(&p_msg->s_msg);
	sem_post(&p_msg->s_empty);
	return TRUE;
}
void* set_func(void* args)
{
	int index = 100;
	
	while(1)
	{
		put_msg(p_msg, index);
		printf("set %d\n", index);
		index ++; sleep(1);
	}
	return NULL;
}
void* get_func(void* args)
{
	int data;
	while(1)
	{
		get_msg(p_msg, &data);
		printf("get %d\n", data);
		sleep(1);
	}
	return NULL;	
}
int main(int argc, char* argv[])
{
	pthread_t pid1, pid2;	
	int index;	
	p_msg = alloc_msg(10);
	if(NULL == p_msg)
	{
		goto end;
	}
	if(pthread_create(&pid1, NULL, set_func, NULL))
	{
		goto end;
	}
	if(pthread_create(&pid2, NULL, get_func, NULL))
	{
		goto end;
	}
	while(1)
	{
		sleep(0);
	}
end:
	return 1;
}