Hi everybody,

I'm developing a daemon in c/c++ and I'm having some trouble with shared memory. I create different processes that have to access the same memory region. Everything was OK until I decided to use a vector containing objects. I read that I have to define an allocator specifing how to reserve memory. OK that what I'm trying to do. I have defined my allocator, allocate, and deallocate functions work perfectly but I have problems with the construct function, it simply raises a SIGSEGV.

Is my first time using shared memory and I'm really discouraged. Suggestions and comments are always welcome. Thanks in advance.

#ifndef _NEW_MMAPALLOCATOR_H
#define _NEW_MMAPALLOCATOR_H 1

extern "C"
{
#include <sys/types.h>
#include <sys/mman.h>
}

#include <limits>
#include <vector>
#include <iostream>
#include <iterator>

namespace leimyalloc {
template <typename T>
class mmap_allocator {
public:
	typedef size_t size_type;
	typedef ptrdiff_t difference_type;
	typedef T* pointer;
	typedef T const * const_pointer;
	typedef T& reference;
	typedef T const & const_reference;
	typedef T value_type;

	//rebind
	template <typename U>
	struct rebind {
		typedef mmap_allocator <U> other;
	};

	pointer address (reference value ) const {
		return &value;
	}

	const_pointer address (const_reference value) const {
		return &value;
	}

	mmap_allocator () throw () {}

	mmap_allocator ( mmap_allocator const  &) throw () {}

	template <typename U>
	mmap_allocator (mmap_allocator <U> const &) throw () {}

	~mmap_allocator() throw () {}

	size_type max_size () const throw() {
		return ::std::numeric_limits <size_type>::max() / sizeof(T);
	}

	pointer allocate (size_type num, void *  hint = 0) {
		int fd=open("/dev/zero",O_RDWR);
		if(fd==-1){
			cerr << "Cannot open /dev/zero" << endl;
		}
		pointer p = (pointer) ::mmap(0, sizeof(pointer), PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
		int * val = (int *)p;
		if(val && *val == -1)
		 p = NULL;
		
		return p;
	}

	void construct (pointer p, const_reference value) {
		new((void *)p) T(value);  //placement new
	}

	void destroy (pointer p) {
		p->~T();
	}

	void deallocate (pointer p, size_type num) {
		::munmap((caddr_t) p, num);
	}

};

template <typename T1, typename T2>
bool operator == (mmap_allocator <T1> const &, mmap_allocator <T2> const &) throw () {
	return true;
}

template <typename T1, typename T2>
bool operator != (mmap_allocator <T1> const &, mmap_allocator <T2> const &) throw () {
	return false;
}

}
#end if

> my first time using shared memory and I'm really discouraged.
it is just that the problem is (much) harder than you imagine it to be.

for this to work, a shared memory segment should be created once and when allocate is called we have to sub-allocate memory blocks out of this segment. a good place to learn about a simple way of doing it is to read the section on implementing malloc() and free() in 'The C Programming Language' (Kernighan and Ritchie).

now we encounter the first problem: when creating shared memory (and memory mapped files) to communicate between two processes, the memory segment can be mapped at a different address in each process. a shared memory segment that is just created is merely a raw chunk of memory. in order to implement the allocation mechanism, we need to store pointers inside this shared memory segment. since the normal pointer stores an absolute address, that address is only valid for the process that placed the object there (unless all processes map the mapped region in the same address). to be able to simulate pointers in mapped regions, we have to create a smart pointer that uses offsets instead of absolute addresses. (this would also be true for user-defined objects that are placed into shared memory; any pointer member must be a smart pointer. and there can be no reference members at all).

the second problem is much simpler to solve; we need to synchronize access to the shared memory structures from multiple processes.

there are several other issues to be addressed. for details, see the documentation for boost.interprocess library (still in vault) at http://igaztanaga.drivehq.com/interprocess/

Thank you very much for the info. I will keep on trying. And yes you're right is much more difficult than I thought. I will try to use Boost libraries, they seem simple to be used.

Cheers

This article has been dead for over six months. Start a new discussion instead.