一个简单的用信号灯来同步的共享内存类

2013年8月28日 由 Creater 留言 »

共享内存是速度较快的IPC了。以下提供一个共享内存类。代码很简单,不用多的解释。
robot_shm_buffer.h

#ifndef ATU_SHM_BUFFER_H_
#define ATU_SHM_BUFFER_H_
#include <string>
#include <fcntl.h>
#include <semaphore.h>

namespace atu_libs {

namespace atu_shm_buffer {

const u_int c_default_buffer_len = 256;

class atu_shm_buffer {
public:
	/*
	 *  Constructor of atu_shm_buffer.
	 *  @name:     the name of the shared memory.
	 *  @len:      if first created, specify the length of the shared memroy.
	 *  @create:   true create a new shared memory, false link to an exist shared memory.
	 */
	atu_shm_buffer(const char *name, size_t len = c_default_buffer_len, bool create = false);
	virtual ~atu_shm_buffer();

	/*
	 *  Get the name of the shared memory.
	 *  Return value: the name of the shared memory.
	 */
	inline const char * get_name(void) { return m_name.c_str(); }
	/*
	 *  Get the length of the shared memory.
	 *  Return value: the length of the shared memory.
	 */
	inline size_t get_len(void) { return m_len; }

	/*
	 *  Read from shared memory. Use a semaphore with the same name to synchronize.
	 *  @buf:    the point to a buffer, the buffer must be allocated.
	 *  @len:    the length of bytes read from shared memory.
	 */
	void read(char *buf, size_t len);
	/*
	 *  Write bytes to shared memroy. Use a semaphore with the same name to synchronize.
	 *  @content:  the point to a buffer with contents, the buffer must be allocated.
	 *  @len:      the length of bytes write to shared memory.
	 */
	void write(const void *content, size_t len);
	/*
	 *  Unlink the shared memory and semaphore from linux kernel.
	 */
	void unlink(void);
private:
	void *m_buf;
	size_t m_len;
	int m_fd;
	std::string m_name;

	sem_t *m_sem;
	struct stat m_stat;
};
}
}

#endif /* ATU_SHM_BUFFER_H_ */

robot_shm_buffer.cpp

#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "robot_shm_buffer.h"

namespace atu_libs {

namespace atu_shm_buffer {
/*
 *  Constructor of atu_shm_buffer.
 *  @name:     the name of the shared memory.
 *  @len:      if first created, specify the length of the shared memroy.
 *  @create:   true create a new shared memory, false link to an exist shared memory.
 */
atu_shm_buffer::atu_shm_buffer(const char *name, size_t len, bool create)
: m_buf(NULL)
, m_len(len)
, m_name(name)
{
	assert(NULL != name);

	int ret(0);

	//Link to the shared memory.
	if (create)
	{
		m_fd = shm_open(name, O_RDWR | O_CREAT, 0644);

		//create a semaphore for w/r operation.
		m_sem = sem_open(name, O_CREAT, 0644, 1);
		if (SEM_FAILED == m_sem)
		{
			fprintf(stderr, "Failed to create semaphore %s!\n", name);
			return;
		}
		//set the size of the shared memory.
		ret = ftruncate(m_fd, len);
		if (-1 == ret)
		{
			fprintf(stderr, "Failed to re-size shared memory buffer %s!\n", name);
			return;
		}
	}
	else
	{
		m_fd = shm_open(name, O_RDWR, 0644);
		//set a sem for w/r operation.
		m_sem = sem_open(name, O_RDWR);
		if (SEM_FAILED == m_sem)
		{
			fprintf(stderr, "Failed to create semaphore %s!\n", name);
			return;
		}
	}
	if (-1 == m_fd)
	{
		fprintf(stderr, "Failed to create shared memory buffer %s!\n", name);
		return;
	}

	//get shared memory status.
	ret = fstat(m_fd, &m_stat);
	if (-1 == ret)
	{
		fprintf(stderr, "Failed to get status of shared memory!\n");
		return;
	}
	m_len = m_stat.st_size;

	//map the shared memory to buffer.
	m_buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0);
	if (MAP_FAILED == m_buf)
	{
		perror("Failed to map shared memory to process!");
		return;
	}

	//If the shared memory is created for the first time, initialize it.
	if (create)
	{
		memset(m_buf, 0, len);
	}
}

atu_shm_buffer::~atu_shm_buffer() {
	if (-1 != m_fd)
	{
		munmap(m_buf, m_len);
	}

	//!!!If you want to unlink semaphore and shared memory, please use function unlink().
}

/*
 *  Unlink the shared memory and semaphore from linux kernel.
 */
void atu_shm_buffer::unlink(void)
{
	if (MAP_FAILED != m_buf)
	{
		sem_unlink(m_name.c_str());
		shm_unlink(m_name.c_str());
	}
}

/*
 *  Read from shared memory. Use a semaphore with the same name to synchronize.
 *  @buf:    the point to a buffer, the buffer must be allocated.
 *  @len:    the length of bytes read from shared memory.
 */
void atu_shm_buffer::read(char *buffer, size_t len)
{
	if (len > m_len)
	{
		fprintf(stderr, "[read] Buffer is truncated! From %d to %d bytes.\n",
				(int)len, (int)m_len);
		len = m_len;
	}
	sem_wait(m_sem);
	memcpy((void *)buffer, m_buf, len);
	sem_post(m_sem);
}

/*
 *  Write bytes to shared memroy. Use a semaphore with the same name to synchronize.
 *  @content:  the point to a buffer with contents, the buffer must be allocated.
 *  @len:      the length of bytes write to shared memory.
 */
void atu_shm_buffer::write(const void* buffer, size_t len)
{
	if (len > m_len)
	{
		fprintf(stderr, "[write] Buffer is truncated! From %d to %d bytes.\n",
				(int)len, (int)m_len);
		len = m_len;
	}
	sem_wait(m_sem);
	memcpy(m_buf, buffer, len);
	sem_post(m_sem);
}

}
}
广告位

发表评论

你必须 登陆 方可发表评论.