多线程管道通信

通过多线程实现管道通讯

头文件:mypipe.h

#ifndef __PIPE_H__
#define __PIPE_H__

#define PIPE_RD 0x00000001UL   //只读属性
#define PIPE_WR 0x00000002UL //只写属性
#define MAXLENTH 1024

typedef void mypipe_st;

mypipe_st *pipe_init(void);
int pipe_register(mypipe_st *,int mode);
int pipe_unregister(mypipe_st *,int mode);
int pipe_read(mypipe_st *,void *,size_t);
int pipe_write(mypipe_st *,const void *,size_t);
int pipe_destroy(mypipe_st *);

#endif

 

文件:mypipe.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>
#include "pipe.h"

struct pipe_st  //自定义管道数据
{
  int head;
  int tail;
  int lenth;
  char buff[MAXLENTH];
  int count_rd;
  int count_wr;
  pthread_mutex_t mut;
  pthread_cond_t cond;
};

mypipe_st *pipe_init(void)  //初始化管道
{
  struct pipe_st *me;

  me = malloc(sizeof(*me));
  if(me == NULL)
    return NULL;

  me->head = 0;
  me->tail =0;
  me->lenth =0;
  me->count_rd =0;
  me->count_wr =0;
  pthread_mutex_init(&me->mut,NULL);
  pthread_cond_init(&me->cond,NULL);

  return me;
}

int pipe_register(mypipe_st *ptr,int mode)  //注册属性   读用户或写用户
{
  struct pipe_st *me = ptr;

  if(ptr ==NULL || mode ==0)
    return -EINVAL;

  pthread_mutex_lock(&me->mut);
  if(mode & PIPE_RD)
    me->count_rd++;
  if(mode & PIPE_WR)
    me->count_wr++;
  pthread_cond_broadcast(&me->cond);
  while(me->count_rd<=0 || me->count_wr<=0)   //当读用户或写用户为0 时阻塞等待
    pthread_cond_wait(&me->cond,&me->mut);

  pthread_mutex_unlock(&me->mut);

  return 0;
}

int pipe_unregister(mypipe_st *ptr,int mode) //注销属性  读用户或写用户
{
  struct pipe_st *me = ptr;

  if(ptr ==NULL || mode ==0)
    return -EINVAL;

  pthread_mutex_lock(&me->mut);
  if(mode & PIPE_RD)
    me->count_rd--;
  if(mode & PIPE_WR)
    me->count_wr--;
  pthread_cond_broadcast(&me->cond);
  while(me->count_rd<=0 || me->count_wr<=0)   //当读用户或写用户为0 时阻塞等待
    pthread_cond_wait(&me->cond,&me->mut);

  pthread_mutex_unlock(&me->mut);

  return 0;
}

static int pipe_read_byte_unlock(struct pipe_st *me,void *buff)   //读取一字节数据
{
  char *str = buff;

  if(me->lenth <=0)
    return -1;
  str[0] = me->buff[me->head];
  me->head = (me->head+1)%MAXLENTH;
  me->lenth--;

  return 0;
}

int pipe_read(mypipe_st *ptr,void *buff,size_t count)  //读取数据
{
  struct pipe_st *me = ptr;
  int i;

  if(ptr == NULL || buff ==NULL || count<=0)
    return -EINVAL;

  pthread_mutex_lock(&me->mut);
  if(me->lenth <=0 && me->count_wr<=0)   //当数据位0 且没有写用户时解锁退出
  {
    pthread_mutex_unlock(&me->mut);
    exit(0);
  }
  while(me->lenth<=0)  //无数据时解锁等待
    pthread_cond_wait(&me->cond,&me->mut);

  for(i=0;i<count;i++)  //循环读取数据
  {
    if(pipe_read_byte_unlock(me,buff+i)<0)
      break;
  }
  pthread_cond_broadcast(&me->cond);
  pthread_mutex_unlock(&me->mut);

  return i;
}

static int pipe_write_byte_unlock(struct pipe_st *me,const void *buff)  //写一字节数据
{
  const char *str = buff;

  if((me->tail+1)%MAXLENTH!=me->head)
  {
    me->buff[me->tail] = str[0];
    me->tail = (me->tail+1)%MAXLENTH;
    me->lenth++;

    return 0;
  }

  return -1;
}

int pipe_write(mypipe_st *ptr,const void *buff,size_t count) //写数据
{
  struct pipe_st *me = ptr;
  int i;

  if(ptr == NULL|| buff==NULL ||count<=0)
    return -EINVAL;

  pthread_mutex_lock(&me->mut);
  if(me->lenth<=0 && me->count_rd<=0)   //当数据长度为0 且没有读用户时退出
  {
    pthread_mutex_unlock(&me->mut);
    exit(0);
  }
  while(me->lenth == MAXLENTH-1) //当数据满时等待
    pthread_cond_wait(&me->cond,&me->mut);

  for(i=0;i<count;i++)  //循环写入数据
  {
    if(pipe_write_byte_unlock(me,buff+i)<0)
    break;
  }
  pthread_cond_broadcast(&me->cond);
  pthread_mutex_unlock(&me->mut);

  return i;
}

int pipe_destroy(mypipe_st *ptr)  //销毁管道
{
  struct pipe_st *me = ptr;

  pthread_mutex_destroy(&me->mut);
  pthread_cond_destroy(&me->cond);
  free(me);

  return 0;
}

 

主文件:main.c

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include "pipe.h"

static mypipe_st *me;

static void *pth_handler(void *p)  //线程任务
{
  int ret;

  char str[] = "hello world! this is a test.";
  pipe_register(me,PIPE_WR);    //注册写用户
  ret = pipe_write(me,str,strlen(str));  //多次写数据
  ret = pipe_write(me,str,strlen(str));
  ret = pipe_write(me,str,strlen(str));
  ret = pipe_write(me,str,strlen(str));
}

int main()
{
  char buff[64];
  int ret,err;
  pthread_t tid;

  me = pipe_init();  //初始化管道
  if(me ==NULL)
  {
    fprintf(stderr,"pipe_init error\n");
    exit(1);
  }

  err = pthread_create(&tid,NULL,pth_handler,NULL);  //创建新线程
  if(err)
  {
    fprintf(stderr,"pthread_create() %s\n",strerror(err));
    exit(1);
  }

  pipe_register(me,PIPE_RD);  //注册读用户

  memset(buff,0,64);
  ret = pipe_read(me,buff,63);  //多次读数据
  printf("read:%d\n",ret);
  puts(buff);


  memset(buff,0,64);
  ret = pipe_read(me,buff,63);
  printf("read:%d\n",ret);
  puts(buff);

  pthread_join(tid,NULL); //等待子线程结束
  pipe_destroy(me);  //销毁管道
  exit(0);
}

 

编译文件:Makefile

CFLAGS +=-pthread
LDFLAGS +=-pthread

pipe:pipe.o main.o
  $(CC) $^ -o $@ $(CFLAGS) $(LDFLAGS)

clean:
  $(RM) *.o pipe

posted @ 2022-08-02 14:41  *^VV^*  阅读(102)  评论(0编辑  收藏  举报