多线程管道通信
通过多线程实现管道通讯
头文件: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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现