Linux下的pv操作

发表于:2012-8-20 09:55

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:feixiaoxing    来源:51Testing软件测试网采编

  关于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;
}

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号