IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 模拟信号量对buffer读写 -> 正文阅读

[C++知识库]模拟信号量对buffer读写

1.demo2.c
主要解决内存满了问题和读写速度不一致问题即读的比写的快。

#include <stdio.h>
#include <pthread.h>
#include <string.h>
#include "demo2.h"
#define MAX_BUFFER_NUM  5
#define MAX_DATA_LENGTH 1024

 /* 设置句柄类 */
typedef struct {
		char                abyBuf[MAX_DATA_LENGTH]; /* 存放的数据量 */
        int                 nBufferldx;
		int                 nBufferEnable; /* buffer是否被占用 */
	    int                 nWriteBufferLength; /* buffer内写入的数据量此buffer最多可以
	                                         写入2的32次方减一的数据 */

		int                 nReadBufferLength;/* buffer内读出的数据 */
		int                 bWait;            /* 条件等待标志位 */
		pthread_mutex_t     tBufferMutex;     /* buffer访问时线程锁 */
		pthread_cond_t      tBufferReadCond;  /* 条件变量 */
}TBufferlnf;		


static TBufferlnf g_tBufferInf[MAX_BUFFER_NUM];/* 缓冲池的最大数量为结构体数组 */

/* 1. 创建buffer
 * 2. 销毁buffer
 * 3. 往buffer送数据
 * 4. 往buffer取数据
 * 5. 获取buffer状态
 *
 */



/* 主要解决问题 */
/* 1.读的比写的快怎么办,Buffer满了怎么办 */




/* 显示当前Buffer的状态 */
void show_Buffer_Inf(void **pptHandle)
{
	TBufferlnf *ptHandle = (TBufferlnf *)*pptHandle;
	printf("nIdx=%d\n", ptHandle->nBufferldx);
	printf("nEnable=%d\n", ptHandle->nBufferEnable);
	printf("data nReadBufferLength=%d\n", ptHandle->nReadBufferLength); 
	printf("data nWriteBufferLength=%d\n", ptHandle->nWriteBufferLength);	
}


int get_Data_From_Buffer(void **pptHandle, void *data,
                       int  nDataLength) /* data为主函数将要拷贝到的内存块 */
                                     
{
	
	TBufferlnf *ptHandle = (TBufferlnf *)*pptHandle;
    int         nReadLength;
	int         nNowDataLocation;
	int         nDiff;

	if ((pptHandle == NULL) || (data == NULL))
	{
		printf("input param error, ptHandle=%p, data=%p\n", ptHandle, data);
		return -1;
	}
	
	if (nDataLength >= MAX_DATA_LENGTH) /* 如果获得的数据大于等于可以存放的数据量 */
	{
    	printf("input param error, nDataLength=%d", nDataLength);	
		
        return -2;
	}
	pthread_mutex_lock(&(ptHandle->tBufferMutex)); /* 读的数据一定要比写的慢 */
	nDiff = ptHandle->nWriteBufferLength - ptHandle->nReadBufferLength; /* 写的数据与读的数据只差 */
	if (nDiff > MAX_DATA_LENGTH) /* 如果差大于内存块大小则报错 */
	{
		printf(" nDiff error, nDiff=%d\n", nDiff);
		return -3;
	}
    while (ptHandle->nWriteBufferLength < ptHandle->nReadBufferLength) /* 因为读的数据一定要比写的慢所以当写的数据少于
                                                                读的数据时条件等待等待数据生产 */
    {
        ptHandle->bWait = 1;
        printf("waiting for product\n");
		pthread_cond_wait(&(ptHandle->tBufferReadCond), &(ptHandle->tBufferMutex));
		
    }
	nNowDataLocation = (ptHandle->nReadBufferLength) % MAX_DATA_LENGTH;		/* 数据的当前位置长度 */											
	ptHandle->nReadBufferLength += nDataLength;
	if (ptHandle->nReadBufferLength >= MAX_DATA_LENGTH)
	{
    	nReadLength = (ptHandle->nReadBufferLength) % MAX_DATA_LENGTH;
		memcpy((char *)data, &(ptHandle->abyBuf[nNowDataLocation]), (MAX_DATA_LENGTH-nNowDataLocation));
		memcpy(((char *)data + MAX_DATA_LENGTH - nNowDataLocation), &(ptHandle->abyBuf[0]),
					nReadLength);
	}
	else
	{
		memcpy((char *)data, &(ptHandle->abyBuf[nNowDataLocation]), nDataLength);
	}
	
    pthread_mutex_unlock(&(ptHandle->tBufferMutex));

	return 0;
	
}


int send_Data_To_Buffer(void **pptHandle, void *data, 
                               int nDataLength)
{
	TBufferlnf *ptHandle = (TBufferlnf *)*pptHandle;
	int         nNowDataLocation; /* 未存入数据时的位置 */
    int         nWriteLength; /* 越界开始从头写入的数据量 */

	
    if ((pptHandle == NULL) || (data == NULL))
	{
		printf("input param error, ptHandle=%p, data=%p\n", ptHandle, 
			                                                     data);
		return -1;
	}
	
	if ((nDataLength <= 0) || (nDataLength >= MAX_DATA_LENGTH)) /* 如果获得的数据大于等于可以存放的数据量 */
	{
    	printf("input param error, nDataLength=%d\n", nDataLength);	
		
        return -2;
	}
	
	pthread_mutex_lock(&(ptHandle->tBufferMutex));
	nNowDataLocation = (ptHandle->nWriteBufferLength) % MAX_DATA_LENGTH; /*  比如说原来的数据245取余是245得到 ,
	                                                                ptHandle->nWriteBufferLength比MAX_DATA_LENGTH小时取余算出的是当前自已的值 */
	ptHandle->nWriteBufferLength += nDataLength; 
	if (ptHandle->nWriteBufferLength >= MAX_DATA_LENGTH) /* 如果拷贝数据加上原有数据大于等于buffer长度 */
	{
		nWriteLength = (ptHandle->nWriteBufferLength) % MAX_DATA_LENGTH; /* 取余算出超出来的数据,  
		                                                          ptHandle->nWriteBufferLength比MAX_DATA_LENGTH大时取余算出超出的部分*/
		memcpy(&(ptHandle->abyBuf[nNowDataLocation]), (char *)data, (MAX_DATA_LENGTH - nNowDataLocation)); /* 先拷贝内存中剩下可以容纳的数据量 */
        memcpy(&(ptHandle->abyBuf[0]), ((char *)data + MAX_DATA_LENGTH - nNowDataLocation), nWriteLength);  /* 接着拷贝超出的数据,也就是data剩下的数据 */
	
	}
	else
	{
	memcpy(&(ptHandle->abyBuf[nNowDataLocation]), (char *)data, nDataLength);
	}
	if (ptHandle->bWait == 1)   /* 防止一开始发送信号,一开始写数据比读数据多有信号,下一秒数据消耗比读数据少时
	                         会认为已经有了信号出BUG,所以先要有条件判断 */
	{
		if (ptHandle->nWriteBufferLength > ptHandle->nReadBufferLength)
		{
	    printf("send signal to consumer\n");
		ptHandle->bWait = 0;
		pthread_cond_signal(&(ptHandle->tBufferReadCond)); /* 发送信号的过程,假如上一秒发送信号,
		                                                下一秒写数据量少于读数据量又去接收到信号继续拷贝数据,所以常常伴随条件变量bWait */
		}
	}
	pthread_mutex_unlock(&(ptHandle->tBufferMutex));
	
    return 0;

}



int destory_Buffer(void **pptHandle)
{
	 if (*pptHandle == NULL) /* 内存块空就报错 */
    {
		return -1;
    }
	TBufferlnf  *ptHandle = (TBufferlnf*)(*pptHandle);
    ptHandle->nBufferEnable = 0;
		
	return  0; 
}



/*  pptHandle是二级指针保存一级指针的地址,*pptHandle可以得到一级指针变量里面存的内容即变量的地址,**pptHandle得到原本变量里面的值 */


int create_Buffer(void **pptHandle) 
{
	int nIdx    = 0;
	*pptHandle = NULL;
	for (nIdx = 0; nIdx < MAX_BUFFER_NUM; nIdx++) /* 寻找未被占用的buffer */
	{
		pthread_mutex_lock(&(g_tBufferInf[nIdx].tBufferMutex)); 
        if (!g_tBufferInf[nIdx].nBufferEnable) /* 内存块没有被占用时 */
        {
        *pptHandle 	= &g_tBufferInf[nIdx]; /* 取*一次就是内存块变量地址 */
        g_tBufferInf[nIdx].nBufferEnable = 1;/* 代表内存块被占用 */	 	
        pthread_mutex_unlock(&(g_tBufferInf[nIdx].tBufferMutex));
		break; /* 找到后跳出 */
        }
	}
    if (*pptHandle == NULL) /* 内存块空就报错 */
    {
		return -1;
    }
	return 0;
	
}


/* 初始化Buffer,清空buffer和定义互斥条件变量 */
void buffer_Init()
{
    int nIdx = 0;
	memset(&g_tBufferInf[0], 0, sizeof(TBufferlnf)*MAX_BUFFER_NUM);
    for (nIdx = 0; nIdx < MAX_BUFFER_NUM; nIdx++)
    {
    	pthread_mutex_init(&(g_tBufferInf[nIdx].tBufferMutex), NULL);
        pthread_cond_init(&(g_tBufferInf[nIdx].tBufferReadCond), NULL);
    }
}

2.demo2.h

#ifndef _BUFFER_H
#define _BUFFER_H

void show_Buffer_Inf(void **pptHandle);
int get_Data_From_Buffer(void **pptHandle, void *data,
	                       int  nDataLength);
int send_Data_To_Buffer(void **pptHandle, void *data, 
                           int nDataLength);
int destory_Buffer(void **pptHandle);
int create_Buffer(void **pptHandle);
void buffer_Init();

#endif

3.main.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "demo2.h"


/* 全局变量pHandle */
void *pHandle = NULL; 



/* 生产速度比消费速度快 */
void *WorkProduct(void *arg)
{
	printf("This is product\n");
    while(1)
    {
		send_Data_To_Buffer(&pHandle, "nixu", 4);
		sleep(1);
    }
	return NULL;
}
void *WorkConsmue(void *arg)
{
	printf("This is consume\n");
	char readBuf[128];
    while(1)
    {
		get_Data_From_Buffer(&pHandle, &readBuf[0], 3);
		sleep(1);
		printf("readBuf=%s\n", readBuf);
    }
	return NULL;
 
}

int main()
{
	int nRet = 0;
	pthread_t tCons;
	pthread_t tProd;
	buffer_Init();
    nRet = create_Buffer(&pHandle);  
    if (nRet)
    {
		printf(" create_buffer error nRet=%d", nRet);
        return -1;
    }
    pthread_create(&tCons, NULL, WorkProduct, NULL);
    pthread_create(&tProd, NULL, WorkConsmue, NULL);

	pthread_join(tCons, NULL);
    pthread_join(tProd, NULL);

	return 0;


}

2.编译时出现的报错

(1).||要加括号否则出现错误
在这里插入图片描述
2.GDB调试
在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 15:50:34  更:2022-03-03 15:50:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 7:24:10-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码