编译环境:Ubuntu16.04 64位
交叉编译工具:arm-hisiv500-linux-gcc
1. 背景
最近项目中需要用到多线程通信,取走旧数据,取数据不及时写入覆盖旧数据,队列长度可配置,自己造个轮子吧,对照上一篇linux c共享内存和信号量。
2. 涉及的函数
详细描述可以百度或ubuntu下查询man手册。
互斥锁相关:
int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t * attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
3. 头文件JList.h
#ifndef __J_LIST__
#define __J_LIST__
#ifdef __cplusplus
extern "C" {
#endif
typedef enum _JLIST_ERR{
JLIST_NO_DATA = -4, // 无数据供读取
JLIST_READ_LENGTH_ERR = -3, // 读取缓冲区长度不够
JLIST_WRITE_LENGTH_ERR = -2, // 写入长度超出
JLIST_INIT_FAIL = -1, // 初始化异常
JLIST_OK = 0,
JLIST_WRITE_OVERWRITE = 1, // 写成功,但是覆盖
}JLIST_ERR;
class JList {
public:
JList(unsigned int size, unsigned int blockNum = 0);
~JList();
int Write(unsigned char *buf, unsigned int len);
int Read(unsigned char *buf, unsigned int len);
private:
static unsigned int IsPower2(unsigned int size);
static unsigned int To2N(unsigned int size);
private:
unsigned int m_size; // 内存总大小
unsigned int m_blockSize; // 块大小
unsigned int m_blockNum; // 块数量
unsigned char *m_buffer; // 内存地址
unsigned int m_offset; // 数据偏移量
pthread_mutex_t m_mutex;
};
#ifdef __cplusplus
}
#endif
#endif // __J_LIST__
4. 类的实现
#include <string.h>
#include <stdlib.h>
#include "JList.h"
struct ListHead {
unsigned int readPos; // 读取位置,从0开始,blockNum不为0时有效
unsigned int dataNum; // 数据数量
unsigned int len[0]; // 数据长度,根据blockNum分配
};
unsigned int JLIST::IsPower2(unsigned int size)
{
if (size == 0)
return 0;
return ((size & (size - 1)) == 0);
}
unsigned int JLIST::To2N(unsigned int size)
{
unsigned int i = 1;
unsigned int tmp = size;
while (size >>= 1)
{
i <<= 1;
}
return (i < tmp) ? i << 1 : i;
}
JList::JList(unsigned int blockSize, unsigned int blockNum)
{
unsigned int nSize = IsPower2(blockSize) ? blockSize : To2N(blockSize);
m_blockSize = nSize;
m_blockNum = (blockNum == 0) ? 1 : blockNum;
m_offset = sizeof(ListHead) + sizeof(unsigned int) * m_blockNum;
m_size = m_blockSize * m_blockNum + m_offset;
m_buffer = (unsigned char *)malloc(m_size);
memset(m_buffer, 0, m_size);
pthread_mutex_init(&m_mutex, NULL);
}
JList::~JList()
{
free(m_buffer);
m_buffer = NULL;
pthread_mutex_destroy(&m_mutex);
}
// !!!note:写入内存,写入长度需要小于等于块长度
// buf:要写入的数据
// len:要写入的数据的长度
// 返回值:>=0表示成功,0成功,1覆盖旧数据,-1表示失败
int JList::Write(unsigned char *buf, unsigned int len)
{
if (m_buffer == NULL)
return JLIST_INIT_FAIL;
if (len > m_blockSize)
return JLIST_WRITE_LENGTH_ERR;
int ret = JLIST_OK;
pthread_mutex_lock(&m_mutex);
ListHead *head = (ListHead *)m_buffer;
unsigned int writePos = head->readPos + head->dataNum;
if (writePos >= m_blockNum)
writePos = writePos - m_blockNum;
memcpy(m_buffer + m_offset + m_blockSize * writePos, buf, len);
head->len[writePos] = len;
if (head->dataNum == m_blockNum) // 满的
{
head->readPos = (writePos + 1 >= m_blockNum) ? 0 : writePos + 1;
ret = JLIST_WRITE_OVERWRITE;
}
else
{
head->dataNum = head->dataNum + 1;
}
pthread_mutex_unlock(&m_mutex);
return ret;
}
// !!!note:读取内存,读取长度需要大于等于数据长度
// buf:读数据的缓冲区
// len:缓冲区的长度
// 返回值:实际读取到的长度,<=0表示失败
int JList::Read(unsigned char *buf, unsigned int len)
{
if (m_buffer == NULL)
return JLIST_INIT_FAIL;
int ret = JLIST_OK;
pthread_mutex_lock(&m_mutex);
ListHead *head = (ListHead *)m_buffer;
if (head->dataNum == 0)
{
pthread_mutex_unlock(&m_mutex);
return JLIST_NO_DATA;
}
unsigned int readPos = head->readPos;
if (len < head->len[readPos])
{
pthread_mutex_unlock(&m_mutex);
return JLIST_READ_LENGTH_ERR;
}
memcpy(buf, m_buffer + m_offset + m_blockSize * readPos, head->len[readPos]);
ret = head->len[readPos];
head->readPos = (readPos + 1 >= m_blockNum) ? 0 : readPos + 1;
head->dataNum = head->dataNum - 1;
pthread_mutex_unlock(&m_mutex);
return ret;
}
以上。
转载请注明出处,如有错漏之处,敬请指正。