📄 shared_memory.h
字号:
void decrement_ref_count(void) {--ref_count;} }; // class map_index_t //////////////////////////////////////////////////////////////////// ////// 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. ////// ////// The shared_memory_header is followed in memory by the bit ////// vector which is used to keep track of the shared memory ////// pages which have been allocated versus the shared memory ////// pages which are free and available to be allocated. ////// //////////////////////////////////////////////////////////////////// class shared_memory_header_t { private: // This data must be visible to all shared segment users and it is // stored at the beginning of the shared memory segment const int num_of_pages; // within the segment, tracked separately const int page_size; // segment size = num_of_pages*page_size + // sizeof(header) const int proj_id; // NOTE: proj_id == segment_num allocator_bit_vector::allocator_bit_vector_t bit_vec; const int bit_vec_size; // size of the bit vector const int mem_start_offset; // offset in bytes to usable memory // mem_start_offset = sizeof(header) + // sizeof(bit_vec) const int object_size; // total size including header, // bit_vec, and available space const int shared_memory_addr; // address of shared memory segment // in memory. const int shared_memory_size; // total size of allocated shared // memory segment. // Key value used by ftok, same as the alloc_key char key[name_length]; int header_size; // Create a reference to retrieve an object index map_index_t object_index; locks lock_set; int ref_count; // Used to keep track of how many // objects are referencing or using // the shared_memory_header_t object. // When only one object is referencing // the segment, the value is zero. // When the last object shuts down, // the locks object, lock_set is also // destroyed by teh destructor. public: // constructor // place the bit_vec at the address within the segment // directly after the shared_memory_header_t // so the address is from the beginning of this plus // the size of this. shared_memory_header_t(int num_of_pages, int page_size, allocator_key_t alloc_key, int shared_mem_addr, int sh_mem_size, int proj_id) :// int shmid_val) : num_of_pages(num_of_pages), page_size(page_size), proj_id(proj_id), bit_vec(num_of_pages, // keeps track of pages in shared mem // segment reinterpret_cast<unsigned char*>(this)+ sizeof(shared_memory_header_t)), bit_vec_size((num_of_pages/8) + 1), // mem_start_offset = sizeof(header) + sizeof(bit_vec) mem_start_offset(sizeof(shared_memory_header_t) + bit_vec_size), // offset to usable memory in // segment // includes header, bit_vec, and usable memory. object_size(mem_start_offset + num_of_pages*page_size), shared_memory_addr(shared_mem_addr), shared_memory_size(sh_mem_size), object_index(), lock_set(alloc_key,proj_id) { strcpy(key,alloc_key);// shmid=shmid_val; header_size=sizeof(this); bit_vec.clear_items(0,num_of_pages); // page free/allocated list ref_count = 0;#ifdef DEBUG std::cerr << __FILE__ << ":" << __LINE__ << " shared_memory_header_t()constructor : ref_count : " << ref_count << std::endl;#endif } // constructor // destructor virtual ~shared_memory_header_t() {#ifdef DEBUG std::cerr << __FILE__ << ":" << __LINE__ << " ~shared_memory_header_t()" << std::endl;#endif lock_set.~locks(); }; // copy constructor shared_memory_header_t(const shared_memory_header_t& t) : num_of_pages(t.num_of_pages), page_size(t.page_size), // proj_id(t.proj_id), bit_vec(t.bit_vec), bit_vec_size(t.bit_vec_size), // mem_start_offset = sizeof(header) + sizeof(bit_vec) mem_start_offset(t.mem_start_offset), // includes header, bit_vec, and usable memory. object_size(t.object_size), shared_memory_addr(t.shared_memory_addr), shared_memory_size(t.shared_memory_size), object_index(t.object_index), lock_set(t.lock_set) { strcpy(key,t.key);// shmid=t.shmid; header_size=t.header_size; ref_count = 0;#ifdef DEBUG std::cerr << __FILE__ << ":" << __LINE__ << " shared_memory_header_t()copyconstructor : ref_count : " << ref_count << std::endl;#endif } // copy constructor // assignment operator shared_memory_header_t& operator=(const shared_memory_header_t& t) { if (this != &t) { // avoid self assignment: t=t lock_set=t.lock_set; bit_vec=t.bit_vec; // bit_vec_size=t.bit_vec_size; strcpy(key,t.key);// shmid=t.shmid; header_size=t.header_size; ref_count = 0;#ifdef DEBUG std::cerr << __FILE__ << ":" << __LINE__ << " shared_memory_header_t<>operator= : ref_count : " << ref_count << std::endl;#endif } return *this; } // assignment operator const int get_bit_vec_size() {return bit_vec_size;}// int get_shmid(void) {return shmid;} int get_header_size(void) {return header_size;} int get_proj_id(void) {return proj_id;}// void set_shmid(int val) {shmid=val;} void mark_pages(int page_num, int how_many) {bit_vec.mark_items(page_num,how_many);} void clear_pages(int page_num, int how_many) {bit_vec.clear_items(page_num,how_many);} int find_free_pages(int pages) {return bit_vec.find_free_items(pages);} bool assigned(int page_num) {return bit_vec.assigned(page_num);} int get_page_offset(int page_num); void get_key(char* val) {strcpy(val,key);} void set_key(std::string val) {strcpy(key,val.data());}// // for semaphore locking void lock(int segment_page_num) {lock_set.lock(segment_page_num);} void unlock(int segment_page_num) {lock_set.unlock(segment_page_num);} // for object index information map_index_t get_map_index(void) { // object_index.print(); return object_index; } void set_map_index(map_index_t obj_idx) { object_index=obj_idx; // object_index.print(); } void print_lock_set() const {lock_set.print();} void print() const { std::cerr << "class shared_memory_header_t<>::print()" << std::endl; std::cerr << "\tnum_of_pages: " << num_of_pages << std::endl; std::cerr << "\tpage_size: " << page_size << std::endl; std::cerr << "\tproj_id: " << proj_id << std::endl; std::cerr << "\tbit_vec_size: " << bit_vec_size << std::endl;// std::cerr << "\tshmid: " << shmid << std::endl; std::cerr << "\theader_size: " << header_size << std::endl; lock_set.print(); } // Shared memory synchronize through memory map int sync(void) { int return_val = msync((void*) shared_memory_addr, (size_t) shared_memory_size, MS_SYNC | MS_INVALIDATE); if (return_val == -1) { std::clog << "Status: " << __FILE__ << ':' << __LINE__ ; std::clog << ": shared memory msync: " << strerror(errno) << std::endl; } return return_val; }; const int get_shared_memory_addr() {return shared_memory_addr;} const int get_shared_memory_size() {return shared_memory_size;} int get_ref_count() const {return ref_count;} void set_ref_count(int val) {ref_count=val;} int get_segment_size(void) { return sizeof(mem_space::shared_memory_header_t) + // size of header + ((num_of_pages/8) +1) + // seg bit_vec + num_of_pages*page_size; // usable memory } }; // class shared_memory_header_t //////////////////////////////////////////////////////////////////// ////// Shared Memory //////////////////////////////////////////////////////////////////// ////// ////// Shared Memory is the class interface to the specific ////// operating system. Class Shared is designed to be embedded ////// as an attribute in a higher level class. Shared is ////// expected to be static such that there will be only one ////// instantiated global copy of this class per process. ////// ////// The same shared memory segment address space is mapped ////// differently for each process. Therefore, if the memory ////// view is divided into the individual process view and the ////// overall shared memory segment view which is shared by all ////// the processes, the overall view has assigned different ////// absolute memory addresses for the same physical memory ////// space. So at the overall shared memory level, memory ////// addressing must be accomplished by generic numeric offsets ////// from the beginning memory address (or base address). No ////// absolute addressing should be used. Access from the ////// process level does require absolute addressing methods, ////// and within each process, the addressing scheme of the ////// shared memory segment should be consistent. ////// //////////////////////////////////////////////////////////////////// template<allocator_key_t alloc_key, allocator_addr_t alloc_addr = 0> class shared { public: const int num_of_pages; // number of pages per segment const int page_size; // segment_size = num_of_pages*page_size + // sizeof(header) enum { num_of_segments=127, // using the proj_id in ftok, 1-127 pages // possible. Fixed by ftok bit_vec_size=num_of_segments/8 + 1 // bit vector tracks segments not pages. }; private: const int segment_size; // bit_vec will use bit_vector_buff allocator_bit_vector::allocator_bit_vector_t bit_vec; // Store a single memory segment pointer void* mem_ptr; // contains pointers to memory segments. This is only valid on a // per process basis where the memory pointers are consistent // static void* buffers[num_of_segments]; // shared memory id from shmget on a per segment basis // static int shmid[num_of_segments]; // use same bit_vec paradigm for shared memory but allocate memory // in class as bit_vector_buff for its storage. bit_vec is not // allocated in shared memory as the data is redundant and can be // determined using shmat() to see if anyone else is yet attached // to the memory. This structure also keeps track of a collection // of shared memory segments static unsigned char bit_vector_buff[bit_vec_size]; typedef std::map<std::string, std::pair<void*,struct stat> > mappings_t; static mappings_t mappings; // typedef mappings_t::iterator map_it_t; public: // constructor shared(int num_of_pages, int page_size); // destructor virtual ~shared(); // copy constructor shared(const shared<alloc_key, alloc_addr>& t); // assignment operator shared<alloc_key, alloc_addr>& operator=(const shared<alloc_key, alloc_addr>& t); // allocate does a memory allocate or if the memory segment has // already been allocated, then it does the attach function. If // proj_id == 0, then allocate return the next free, unused // segment. If 1 <= proj_id < 128, then allocate returns a // pointer to the specified segment. memory_index_t allocate(const int& proj_id); // memory_index_t allocate(); bool free(); void unlink(void) { // locate all shared memory segments and unlink them for(mappings_t::iterator it = mappings.begin(); it != mappings.end(); it++) { // find each existing shared memory segement#ifdef DEBUG std::clog << __FILE__ << ':' << __LINE__ << ':' << "shared<>::unlink found and unlinking shared segment: " << it->first << std::endl;#endif shared_memory_header_t* smh = static_cast<shared_memory_header_t*>(it->second.first); smh->~shared_memory_header_t(); shm_unlink(it->first.data()); } // for(mappings_t::iterator it = mappings.begin(); it != mappings.end(); it++) } // void unlink(void) }; // class shared //////////////////////////////////////////////////////////////////////////////// ////// Shared Memory //////////////////////////////////////////////////////////////////////////////// ////// ////// Shared Memory is the class interface to the specific operating system. ////// This is class is user defined and allows the Arena to generate the ////// generic segments of memory which it will provide to the allocator. ////// ////// ////// //////////////////////////////////////////////////////////////////////////////// // The following variables are static, so there is one copy // for all objects instantiated within a process// template<allocator_key_t alloc_key, allocator_addr_t alloc_addr = 0>// int shared<alloc_key, alloc_addr>::shmid[shared::num_of_segments] = {0};// template<allocator_key_t alloc_key, allocator_addr_t alloc_addr = 0>// void* shared<alloc_key, alloc_addr>::buffers[shared::num_of_segments] = {0}; template<allocator_key_t alloc_key, allocator_addr_t alloc_addr = 0> unsigned char shared<alloc_key, alloc_addr>::bit_vector_buff[shared::bit_vec_size] = {0}; template<allocator_key_t alloc_key, allocator_addr_t alloc_addr = 0> std::map<std::string, std::pair<void*,struct stat> > shared<alloc_key, alloc_addr>::mappings; // constructor template<allocator_key_t alloc_key, allocator_addr_t alloc_addr> shared<alloc_key, alloc_addr>::shared(int number_of_pages, int page_sz) : num_of_pages(number_of_pages), page_size(page_sz), // segment pages have no overhead, they are just space // NOTE: the bit_vec in segment size is different than // the bit_vec local to class shared. In shared, // the bit_vec keeps track of the total number of // segments allocated for alloc_key. The bit_vec // used within the segment keeps track of sub- // segment pages of memory. segment_size (sizeof(shared_memory_header_t) + // size of header + ((num_of_pages/8) +1) + // seg bit_vec + num_of_pages*page_size), // usable memory // bit_vec is not allocated in shared memory, but on a // per process basis.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -