⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shared_memory.h

📁 简单的动态内存管理程序源代码
💻 H
📖 第 1 页 / 共 3 页
字号:
    bit_vec(num_of_segments,bit_vector_buff) {    // initialize out to end of the bit_vector buffer    for (int i=0; i<bit_vec_size; i++) {//       shmid[i]=-1;//       buffers[i]=0;      bit_vector_buff[i]=0;    }    mem_ptr = 0;    // finish initializing the other buffers to num_of_segments//    for (int i=bit_vec_size+1; i<num_of_segments; i++) {//       shmid[i]=-1;//       buffers[i]=0;//     }  };  // constructor    // destructor  template<allocator_key_t alloc_key, allocator_addr_t alloc_addr>  shared<alloc_key, alloc_addr>::~shared() {    // Just the bit_vec should be automatically destroyed.    // Opposite of the constructor    // Check the reference count on the shared memory segment    // If last object referencing shared memory, delete it #ifdef DEBUG    std::cerr << __FILE__ << ":" << __LINE__ <<      " ~shared() : mem_ptr : " << mem_ptr << std::endl;#endif    // unmap shared memory    for(mappings_t::iterator it = mappings.begin(); it != mappings.end(); it++) {      // for each segment in the shared object      // if it is not referenced, unlink it#ifdef DEBUG      std::cerr << __FILE__ << ":" << __LINE__ << " ~shared() : alloc_addr : "		<< it->first << std::endl;#endif      shared_memory_header_t* smh = static_cast<shared_memory_header_t*>(it->second.first);      int ref_count = smh->get_ref_count();#ifdef DEBUG      std::cerr << __FILE__ << ":" << __LINE__ << " ~shared() : ref_count : "		<< ref_count << std::endl;#endif      std::cerr.flush();      if (!ref_count) {	smh->~shared_memory_header_t();	int ret_val = munmap(it->second.first, it->second.second.st_size);	if (ret_val == -1) {	  std::clog << "Status: " << __FILE__ << ':' << __LINE__ ;	  std::clog << ": shared memory munmap: " << strerror(errno) << std::endl;	}	// unlink shared memory	std::clog << "Status: " << __FILE__ << ':' << __LINE__ ;	std::clog << ": shared memory shm_unlink called" << std::endl;	ret_val = shm_unlink(it->first.data());	if (ret_val == -1) {	  std::clog << "Status: " << __FILE__ << ':' << __LINE__ ;	  std::clog << ": shared memory shm_unlink: " << strerror(errno) << std::endl;	  std::clog << "Shared memory segement: " << it->first.data() << std::endl;	}#ifdef DEBUG	std::cerr << __FILE__ << ":" << __LINE__ <<	  " ~shared() deleting shm : " << std::endl;#endif	// delete the map key	mappings.erase(it);      }    }  };  // destructor  //     }//     std::map<allocator_key_t,//       std::pair<void*,struct stat> >::iterator it = mappings.find(alloc_key);//     if (it != mappings.end()) {//       // Both initialized and mapped. Retrieve pointer and allocation is over.//       // first, destroy the locks//       } else {// 	// Other process still pointing  to the shared memory.  Do not// 	// remove the  shared memory// 	// Further  do  not   decrement  the  ref_count.   Only  those// 	// functions with actually allocate and deallocate memory from// 	// the  shared  memory  segment  change the  reference  count.// 	// Shared creates a segment if  it does not exist, and removes// 	// it  when  the  reference   count  is  zero  and  it  exits.// 	// Otherwise, the it does not affect the ref_count.// #ifdef DEBUG// 	std::cerr << __FILE__ << ":" << __LINE__ <<// 	  " ~shared() : decrementing ref_count: "  <<// 	  ref_count << std::endl;// #endif//       }  // copy constructor  template<allocator_key_t alloc_key, allocator_addr_t alloc_addr>  shared<alloc_key, alloc_addr>::shared(const shared<alloc_key, alloc_addr>& t)  :    // segment pages have no overhead, they are just space    num_of_pages(t.num_of_pages),    page_size(t.page_size),    segment_size (t.segment_size),    bit_vec(t.bit_vec) {    mem_ptr = t.mem_ptr;    // Most  of the  important shared::shared  attributes  are static.    // therefore there  is only one  version of them declared  for all    // process  objects.  They are  in a  sense global,  and therefore    // need  not be copied,  as the  same verison  is accessed  by all    // objects in the same process.  }; // copy constructor    // assignment operator  template<allocator_key_t alloc_key, allocator_addr_t alloc_addr>  shared<alloc_key,	 alloc_addr>& shared<alloc_key,			     alloc_addr>::operator=(const shared<alloc_key,						    alloc_addr>& t)  {    if (this != &t) {		// avoid self assignment: t=t      mem_ptr = t.mem_ptr;    }    return *this;  };  // assignment operator    ////////////////////////////////////////////////////////////////////  //////    shared<>::allocate(const int& proj_id)  ////////////////////////////////////////////////////////////////////  //////     //////    proj_id -    //////      //////    Creates a  large allocation of  shared memory used  by the  //////    allocator.  Returns a pointer to the newly allocated page,  //////    parameter  indicates if  the page  is newly  allocated and  //////    therefore NOT  initialized, or if the page  was already in  //////    use and simply attached.  //////      //////      //////      ////////////////////////////////////////////////////////////////////  // void* shared::allocate(allocator_key_t key_val) {  template<allocator_key_t alloc_key,	   allocator_addr_t alloc_addr>  memory_index_t shared<alloc_key,     			alloc_addr>::allocate(const int& proj_id) {// 			alloc_addr>::allocate() {    // alloc_key - string describing key name, identifies which     //             shared memory segment.    // returns  a  pointer  to  the newly  allocated  page,  parameter    // indicates  if the  page is  newly allocated  and  therefore NOT    // initialized,  or if  the page  was  already in  use and  simply    // attached.    // All shared memory blocks have the shared memory header class    // instantiated at the beginning of their memory space.	// Variables	//   initialized - describes  whether share memory segment has	//                 header installed.	//   mapped - describes whether the process has already mapped	//            this  shared  memory  segment  into  its virtual	//            memory.		// Possible senarios at this point:	//    1. Brand new shared memory segment, just created for the	//       first time.  Needs to be initiallized and mapped.	//    2. Existing shared memory segment:	//       a. Process has already  mapped this segment, retrieve	//          pointer from stored mapping	//       b. 1st time process is accessing this shared segment.	//          The segment needs to be mapped into this process's	//          shared memory space.    void* ptr = (void*) -1;    bool initialized = false;    struct stat stat;    int fd;            // open shared memory    // first try to open shared memory as if it already exists    // if that fails, create the shared memory and initialize it    std::stringstream alloc_key_ss;    // create the shared segment key    alloc_key_ss << alloc_key << "_" << proj_id;#ifdef DEBUG    std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : alloc_key_ss.str().data() : "	      << alloc_key_ss.str().data() << std::endl;#endif    if ((fd = shm_open(alloc_key_ss.str().data(), O_RDWR, S_IRWXU | S_IRWXG)) == -1) {      // Opening existing shared memory failed.  Create it.      fd = shm_open(alloc_key_ss.str().data(), O_RDWR|O_CREAT, S_IRWXU | S_IRWXG);      // now needs to be mapped      // truncate it to required size      if (ftruncate(fd, (off_t)segment_size) != -1) {	// get info on the shared memory segment file descriptor	fstat(fd, &stat);	// After  truncating the  file descriptor,  see if  the shared	// memory is already  mapped?  If so, return a  pointer to the	// existing mapped shared memory; otherwise, map it.	// convert the shared memory's requested address	// from its char string to an number.	std::string stringval(alloc_addr);	std::istringstream sin(stringval);	int x;	sin >> std::hex  >> x;		// add an offset based on the proj_id to the memory address	x = x + segment_size*(proj_id-1);#ifdef DEBUG	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : alloc_addr : "		  << alloc_addr << std::endl;	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : x : "		  << std::hex << x << std::dec << std::endl;#endif	// map shared memory	ptr =	  mmap((void*) x, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);	// mmap((void*) x, stat.st_size, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_SHARED, fd, 0);	if (ptr != MAP_FAILED) {	  //	    if (msync((void*) x, stat.st_size, MS_SYNC | MS_INVALIDATE) != -1) {	  // Install the memory header in the allocated shared memory	  // ref_count will be set to 0 by the constructor	  memset(ptr,0,stat.st_size);	  new(ptr)shared_memory_header_t(num_of_pages,					 page_size,					 alloc_key_ss.str().data(),					 (int) ptr,					 stat.st_size,					 proj_id);  // shmid	  // store off the successful mapping for future retrieval#ifdef DEBUG	  std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : " <<	    "Inserting map val alloc_key_ss.str() : "		    << alloc_key_ss.str() << std::endl;#endif	  mappings.insert(std::pair<std::string,			  std::pair<void*,struct stat> >(alloc_key_ss.str(),							 std::pair<void*,struct stat>(ptr,stat)));	}  else { // if (ptr != MAP_FAILED)	  // create an error message to throw with the exception	  std::stringstream s;	  s << "Error: " << __FILE__ << ':' << __LINE__ << ':'	    << " memory map mmap failed : " << strerror(errno) <<	    std::endl;	  std::clog << s;	  throw (Alloc_Exception::mmap_exception(s.str()));	}  // if (ptr != MAP_FAILED)      } else {  // if (ftruncate(fd, (off_t)segment_size) != -1)	// create an error message to throw with the exception	std::stringstream s;	s << "Error: " << __FILE__ << ':' << __LINE__ << ':'	  << " shared memory ftruncate: " << strerror(errno) <<	  std::endl;	std::clog << s;	throw (Alloc_Exception::shm_exception(s.str()));      }  // if (ftruncate(fd, (off_t)segment_size) != -1)    } else {  // if ((int fd = shm_open(alloc_key, O_RDWR, S_IRWXU | S_IRWXG)) == -1)      // shared memory already exists.  See if it has been mapped into      // this process's memory?      std::map<std::string,	std::pair<void*,struct stat> >::iterator it = mappings.find(alloc_key_ss.str());      if (it != mappings.end()) {	// shared memory segment has already been mapped into this segment	initialized = true;	ptr = it->second.first;      } else {  // if (it != mappings.end())	// shared memory segment has not yet been mapped	// memory map it	fstat(fd, &stat);	// convert the shared memory's requested address	// from its char string to an number.	std::string stringval(alloc_addr);	std::istringstream sin(stringval);	int x;	sin >> std::hex  >> x;	// add an offset based on the proj_id to the memory address	x = x + segment_size*(proj_id-1);#ifdef DEBUG	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : alloc_addr : "		  << alloc_addr << std::endl;	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : x : "		  << std::hex << x << std::dec << std::endl;#endif	ptr =	  mmap((void*) x, stat.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);	// mmap((void*) x, stat.st_size, PROT_READ | PROT_WRITE, MAP_FIXED|MAP_SHARED, fd, 0);	if (ptr == MAP_FAILED) {	  // create an error message to throw with the exception	  std::stringstream s;	  s << "Error: " << __FILE__ << ':' << __LINE__ << ':'	    << " memory map mmap failed : " << strerror(errno) <<	    std::endl;	  std::clog << s;	  throw (Alloc_Exception::mmap_exception(s.str()));	}  // if (ptr == MAP_FAILED)	// store off the successful mapping for future retrieval#ifdef DEBUG	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : " <<	  "Inserting map val alloc_key_ss.str().data() : "		  << alloc_key_ss.str().data() << std::endl;#endif	mappings.insert(std::pair<std::string,			std::pair<void*,struct stat> >(alloc_key_ss.str(),						       std::pair<void*,struct stat>(ptr,stat)));	// Do not touch the  reference count, ref_count.  Only objects	// which allocate  and deallocate  memory from the  segment to	// the allocator  touch the reference counter.   If the shared	// object deconstructs  and the ref_count  is 0, it  takes the	// whole  segement  down   with  it.   Otherwise  the  segment	// persists.#ifdef DEBUG	shared_memory_header_t* smh = static_cast<shared_memory_header_t*>(ptr);	int ref_count = smh->get_ref_count();	std::cerr << __FILE__ << ":" << __LINE__ << " shared<>::allocate() : ref_count : "		  << ref_count << std::endl;#endif      }  // if (it != mappings.end())    } // if ((int fd = shm_open(alloc_key, O_RDWR, S_IRWXU | S_IRWXG)) == -1)    mem_ptr = ptr;    return memory_index_t(ptr, proj_id, initialized);      };  // shared<>::allocate(const int& proj_id)       ////////////////////////////////////////////////////////////////////  //////    shared<>::free(memory_index_t mem_idx)  ////////////////////////////////////////////////////////////////////  //////     //////    mem_idx -  contains description of shared  memory block to  //////               be freed by the function.  //////      //////    Release allocated shared memory segment  //////      //////      //////      ////////////////////////////////////////////////////////////////////      // free()  template<allocator_key_t alloc_key, allocator_addr_t alloc_addr>  bool shared<alloc_key, alloc_addr>::free() {        bool return_flag = true;#ifdef DEBUG    std::cerr << __FILE__ << ':' << __LINE__ << ": " << "shared<>::free()" << std::endl;#endif    return return_flag;  }; // bool shared::free(memory_index_t mem_idx)};  // namespace mem_space#endif // SHARED_MEMORY_H

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -