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

📄 shared_memory.cc

📁 简单的动态内存管理程序源代码
💻 CC
字号:
// file: shared_memory.cc// author: Marc Bumble// June 1, 2000// Page memory source for shared memory // Copyright (C) 2000 by Marc D. Bumble//  This program is free software; you can redistribute it and/or//  modify it under the terms of the GNU General Public License//  as published by the Free Software Foundation; either version 2//  of the License, or (at your option) any later version.//  This program is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.//  You should have received a copy of the GNU General Public License//  along with this program; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.#include <shared_memory.h>namespace mem_space {      ////////////////////////////////////////////////////////////////////  //////                             Memory Locks  ////////////////////////////////////////////////////////////////////  //////     //////    Locks are  mutual exclusion locks used  to protect process  //////    from  writing  simultaneously   to  shared  memory.   Each  //////    allocator will  get one semaphore set, and  then with that  //////    semaphore  set, each chunk  will lock  individual elements  //////    with  semaphores from  that  set.  So  each  chunk is  has  //////    access to the semid and the semnum.  A semid is common for  //////    all chunks within a given  allocator, and then each of the  //////    allocator's  chunks will  have its  own  individual semnum  //////    which indicates which semaphore in the semid array.  //////      ////////////////////////////////////////////////////////////////////  // constructor  locks::locks(const mem_space::allocator_key_t& alloc_key,	       const int& proj_id) {    std::string key_file(alloc_key);    // create a file for System V ftok from alloc_key    key_file = std::string("/tmp") + key_file;    // create the empty shm key file, used by ftok()    std::ofstream to(key_file.data());    if (!to) perror("Cannot open key file");    to.close();    // set the semaphore key    key_t mykey = ftok(key_file.c_str(),proj_id);    if (mykey == -1) {      std::clog << "Error:" << __FILE__ << ':' << __LINE__ << ':'		<< " ftok unable to create sem key: " << strerror(errno) 		<< ":  " << key_file << std::endl;      // create an error message to throw with the exception      std::stringstream s;      s << __FILE__ << ':' << __LINE__ << ':'			  << " project id out of range (1 <= proj_id < 128).";      throw (Alloc_Exception::ftok_exception(s.str()));    }    semid = semget(mykey, num_in_array, IPC_CREAT | IPC_EXCL | 0666);//     std::clog << "Status:" << __FILE__ << ':' << __LINE__ << ':'// 	      << " semid: " << semid << "  " << strerror(errno)// 	      << std::endl;    if (semid >= 0) {      // first to create the semaphores      // need to initialize the semaphore set      union semun arg;      struct semid_ds seminfo;      arg.buf = &seminfo;      // set all semaphores to 1 unit avail      // binary locks, ie one process can sieze the lock at a time for each page.      short unsigned sem_vals[num_in_array];       for (int i = 0; i < num_in_array; i++) {	sem_vals[i] = 1;// 	std::clog << "i = " << i << std::endl;      }      arg.array = sem_vals;      if (semctl(semid, 0, SETALL, arg) == -1) {	std::cerr << "File: " << __FILE__ << ':' << __LINE__ << ':'<< "locks::make_lock()";	std::cerr << ": semaphore creation error: " << strerror(errno) << std::endl;	std::stringstream s;	s << __FILE__ << ':' << __LINE__ << ':'	  << " semaphore creation error.";	throw (Alloc_Exception::lock_creation_exception(s.str()));      }    } else {      // The semaphore set already exists      // Do not initialize, just attach and wait until the semaphores are initialized      union semun arg;      struct semid_ds seminfo;      arg.buf = &seminfo;      // wait  at  most for  10  tries to  see  if  the semaphore  get      // initialized by  the process which  created it.  If  within 10      // tests, the process does not get initialized, then fail.      const int& tries = 10;      bool initialized = false;      for (int i = 0; ((i < tries) && (!initialized)); i++) {	// retrieve information on the semaphores	semctl(semid,0,IPC_STAT,arg);	if (arg.buf->sem_otime != 0) {	  initialized = true;	}	sleep(1);      }      if (!initialized) {	std::cerr << "File: " << __FILE__ << ':' << __LINE__ << ':'<< "locks::locks()";	std::cerr << ": semaphore initialization error: " << strerror(errno) << std::endl;	std::stringstream s;	s << __FILE__ << ':' << __LINE__ << ':'	  << " semaphore initialization error.";	throw (Alloc_Exception::lock_creation_exception(s.str()));      }    }  }; // constructor    // destructor  locks::~locks() {    // union semun semctl_arg;    //     for (int i=0; i<num_in_array; i++) {      //      int semctlresult = semctl(semid, i, IPC_RMID, semctl_arg);#ifdef DEBUG    std::cerr << __FILE__ << ":" << __LINE__ << " ~locks()" << std::endl;#endif    int semctlresult = semctl(semid, 0, IPC_RMID);    if ((semctlresult!=0)&&(errno!=EINVAL)) {      std::cerr << __FILE__ << ':' << __LINE__ << " locks::~locks(): ";      std::cerr << " semid: " << semid << "semctlresult: ";      std::cerr << semctlresult << " " << strerror(errno) << std::endl;    }#ifdef SHARED_MEMORY_MESG    std::cerr << "semid: " << semid << " shmctlresult: ";    std::cerr << semctlresult << " " << strerror(errno) << std::endl;#endif    //     }  }; // destructor  // copy consqtructor  locks::locks(const locks& t) {    semid=t.semid;  }; // copy constructor  // assignment operator  locks& locks::operator=(const locks& t) {    if (this != &t) {		// avoid self assignment: t=t      semid=t.semid;    }  // if (this != &t)    return *this;  };  // assignment operator    // equality operator  bool locks::operator==(const locks& t) {    bool flag=false;    if (semid==t.semid) {      flag=true;    }    return flag;  };  // equality operator  // lock print  void locks::print() const {    // print the current semaphore lock values    struct semid_ds seminfo;    union semun arg;    arg.buf = &seminfo;    semctl(semid, 0, IPC_STAT, arg);    //    int nsems = arg.buf->sem_nsems;    unsigned short sem_vals[num_in_array];    arg.array = sem_vals;    semctl(semid, 0, GETALL, arg);    std::cerr << std::endl;    std::cerr << "locks::print()" << std::endl;    std::cerr << "semid    = " << semid << std::endl;    std::cerr << "semval[] = ";    for (int i = 0; i < num_in_array; i++) {      if (!(i%25)) {	std::cerr << std::endl;	std::cerr << "           ";      }      std::cerr << ":" << sem_vals[i];    }    std::cerr << std::endl;  };  //   void locks::lock(int page_num) {    // only set one lock at a time    struct sembuf sem_buf_array[num_in_array];    sem_buf_array[0].sem_num = page_num % num_in_array;    sem_buf_array[0].sem_op = -1;   // take the lock, subtract it away.    sem_buf_array[0].sem_flg = SEM_UNDO;//     std::cerr << __FILE__ << ':' << __LINE__ << ':'<< " locks::lock()";//     std::cerr << "semid: " << semid << std::endl;    int result = semop(semid, sem_buf_array, 1);  // operate on 1 lock at a time    if (result!=0) {      std::stringstream s;      std::cerr << __FILE__ << ':' << __LINE__ << ':'<< " locks::lock()";      std::cerr << ": semaphore lock: " << strerror(errno) << " result: " << result << std::endl;      s << ": semaphore lock errno: " << strerror(errno) << " result: " << result;      s << " lock attempt error." << " semid: " << semid << " page_num: " << page_num;      std::cerr << s .str()<< std::endl;      throw (Alloc_Exception::locking_exception(s.str()));   }	  };  // void lock(int page_num)  //   void locks::unlock(int page_num) {    // only clear one lock at a time    struct sembuf sem_buf_array[1];    sem_buf_array[0].sem_num = page_num % num_in_array;    sem_buf_array[0].sem_op = 1;       // release the lock, add it back    sem_buf_array[0].sem_flg = SEM_UNDO;    int result = semop(semid, sem_buf_array, 1); // operate on 1 lock at a time    if (result!=0) {      std::stringstream s;      std::cerr << __FILE__ << ':' << __LINE__ << ':'<< " locks::unlock()";      std::cerr << ": semaphore unlock: " << strerror(errno) << " result: " << result << std::endl;      s << ": semaphore unlock errno: " << strerror(errno) << " result: " << result;      s << " unlock attempt error." << " semid: " << semid << " page_num: " << page_num;      std::cerr << s .str()<< std::endl;      throw (Alloc_Exception::locking_exception(s.str()));   }	  };  // void unlock(int page_num)      ////////////////////////////////////////////////////////////////////  //////                     class shared_memory_header  ////////////////////////////////////////////////////////////////////  //////     //////    This class is embedded as  the first element in all shared  //////    memory segments.   It contains information  describing the  //////    state of the allocated memory segment.  This class uses no  //////    memory pointers as the  shared memory segment is mapped to  //////    different  addresses  for  different  processes.   So  all  //////    address values must be relative offsets from the beginning  //////    of the allocated segment.  //////      ////////////////////////////////////////////////////////////////////      int shared_memory_header_t::get_page_offset(int page_num) {    // returns the  offset from  the beginning of  the segment  to the    // page  indicated by  page_num.  Just  calculates size  offset in    // terms of  the number of  bytes.  If shm (shared  memory header)    // points to the beginning of the allocated shared memory segment,    // then  the actual  page address  can be  interepreted  using the    // following calls:    //    // int start_page_offset = smh->get_page_offset(start_page4);    // unsigned char* addr = reinterpret_cast<unsigned char*>(smh) +    //                       start_page_offset;    //    // addr  will  then  contain  the correct  memory  address.   This    // approach  is  required because  the  shared  memory segment  is    // memory mapped  to each process  differently, so an  offset from    // the beginning of the segment address is required.    return sizeof(shared_memory_header_t) + bit_vec_size +       page_num*page_size;  }; // get_page_offset()  }  // namespace mem_space

⌨️ 快捷键说明

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