7_Shared_Memory

For processes to work together in a cohesive way to accomplish a unified goal (i.e. System Software), they need to be able to communicate with each other. Thread communication is pretty straight-forward, since threads share memory. Processes do not. Thus, we need some other mechanisms for sharing information. Communication between processes on different machines present even further challenges, since now they need to communicate without sharing any hardware resources, or even operating systems. We can no longer rely on operating system kernel calls for this.
展开查看详情

1.Shared Memory 1 Lecture 7: Inter-Process Communication Shared Memory Learning Goals Explain why processes cannot share local memory as easily as threads Describe a possible mechanism of how processes can share blocks of memory List and describe three levels of persistence of resources Use the CPEN 333 library to create and apply named shared memory objects for inter-process communication List some advantages and drawbacks of shared memory objects Identify which accesses of shared memory need protection or synchronization via a mutex and which don’t, arguing your case © Paul Davies, C. Antonio Sanchez. Not to be copied, used, or revised without explicit written permission from the copyright owner.

2.Interprocess Communication (IPC) Shared Memory 2 For processes to work together in a cohesive way to accomplish a unified goal (i.e. System Software), they need to be able to communicate with each other. Thread communication is pretty straight-forward, since threads share memory. Processes do not . Thus, we need some other mechanisms for sharing information. Communication between processes on different machines present even further challenges, since now they need to communicate without sharing any hardware resources, or even operating systems. We can no longer rely on operating system kernel calls for this.

3.Memory Access Processes 3 Unlike threads within a single process, separate processes do not share address space . Process 1 Memory: Process 2 Memory: 0x10008000: FE 85 23 11 … 0x10008000: E5 64 32 F9 …

4.Memory Protection Shared Memory 4 Furthermore, most operating systems make use of a hardware-based Memory Management Unit (MMU) to enforce protection of process memory. This chip prevents your program accessing random memory that has not been explicitly allocated to it by the OS, generating an Exception or Access violation if your process tries to reach outside of its bounds. The only case where memory can be directly shared between processes is if you’re using a special-purpose device or chip (e.g. in embedded systems). In such cases, that device’s memory space is no longer controlled by the OS at all (that now becomes your job).

5.IPC: How would YOU do it? Shared Memory 5 Let’s say two processes on the same machine DO want to share memory. How would you do it?

6.IPC: Memory Mapped Files Shared Memory 6 Memory mapped files are files whose content is mapped directly to a process’ memory. For efficiency, these files usually only exist in memory (i.e. are never explicitly written to the hard disk). The same contents are mapped to virtual address space in each process that is granted access. Process 1 Memory: Process 2 Memory: 0x0000FFE0: FE 85 23 11 … 0x10008000: FE 85 23 11 … Data In Data Out MASCOT 3 Symbol for a Datapool

7.IPC: Memory Mapped Files Shared Memory 7 Windows: https://msdn.microsoft.com/en-us/library/windows/desktop/aa366551(v=vs.85).aspx CreateFileMapping(...) MapViewOfFile(...) UnmapViewOfFile (...); CloseHandle(...) Linux/OSX: http://pubs.opengroup.org/onlinepubs/009695399/functions/shm_open.html shm_open(...) mmap(...) munmap (...) close(...) shm_unlink(...) We can create these shared memory objects , also sometimes simply called shared memory or datapools , using operating system kernel calls.

8.IPC: Shared Memory Shared Memory 8 Rather than working directly with operating system calls, we provide a uniform interface in the CPEN 333 course library: class shared_memory : public impl::named_resource_base { public : shared_memory( const std::string &name, size_t size, bool readonly = false ); ~shared_memory(); void * get(size_t offset = 0 ); // get pointer at offset uint8_t& operator [](size_t offset); // access a byte directly bool unlink(); // unlinks name (OSX/Linux) };

9.“Named” Resources Shared Memory 9 So far, we have seen two inter-process resources that we have accessed using a name : mutexes , and now shared memory . This is a common way for the operating system to connect resources between processes. Each must supply the same name in order to connect to the same resource. If a resource with the given name does not already exist, the operating system will create and initialize it. If it does exist, the OS will return the existing one.

10.Persistence Shared Memory 10 Process Persistence: the resource will exist as long as at least one process still has a reference to it. Kernel Persistence: the resource will exist as long as the kernel is running – i.e. until the next reboot. Filesystem Persistence: the resource is backed by the filesystem (will persist even after reboot). On Windows, all named resources have process persistence . On OSX/Linux, they have kernel persistence . A named resource on OSX/Linux can have its name “unlinked” so that future references to the name will create a new resource.

11.Unlinking Named Resources Shared Memory 11 *NIX Kernel cpen333 :: process :: mutex mutex1( "process_mutex" ); mutex: "process_mutex" cpen333 :: process :: mutex mutex2( "process_mutex" ); mutex1.unlink(); cpen333 :: process :: mutex mutex3( "process_mutex" ); mutex: "process_mutex" *NIX Kernel cpen333 :: process :: shared_memory shm1( " shared_memory " , 100 ); memory: “shared_memory" cpen333 :: process :: shared_memory shm2( " shared_memory " , 100 ); shm1.unlink(); cpen333 :: process :: shared_memory shm3( " shared_memory" , 100); memory: “shared_memory"

12.IPC: Shared Memory Shared Memory 12 #include <cstring> #include <string> #include <cpen333/process/shared_memory.h> // Shared data structure struct SharedData { int num ; char str [ 100 ]; }; int main() { cpen333 :: process :: shared_memory memory( "memory_mapped_file" , sizeof ( SharedData )); // get pointer to shared memory SharedData * shared = ( SharedData *)memory.get(); // set values shared-> num = 100 ; std :: string msg = "Hello, world!" ; std ::strncpy(shared-> str , msg.c_str(), msg.length()); // wait for input cpen333 ::pause(); return 0 ; } Why? Why?

13.IPC: Shared Memory Shared Memory 13 Process 1 Memory: Process 2 Memory: 0x0000FFE0: FE 85 23 11 … 0x10008000: FE 85 23 11 … What would happen if you wrote a pointer to a file?

14.IPC: Shared Memory Shared Memory 14 What would happen if you wrote a pointer to a file? Address won’t match in other processes. What if you could enforce consistent addresses? Content “pointed” to would also have to be in shared memory Implications: Avoid use of pointers Avoid use of objects that may contain pointers as members Avoid strings, containers in standard template library

15.IPC: Shared Memory Shared Memory 15 Handling memory layout/organization must be done manually. // 100 MB cpen333 :: process :: shared_memory memory( "big_memory_block" , 100000000 ); int * x1 = ( int *)memory.get( 512 ); double * x2 = ( double *)memory.get( 514 ); Car * car = ( Car *)memory.get( 8889823 ); Easiest if laid out in a common struct definition: struct MemoryLayout { int x1; double x2; Car car; }; cpen333 :: process :: shared_memory memory( "big_memory_block" , sizeof ( MemoryLayout )); MemoryLayout * data = ( MemoryLayout *)memory.get(); data-> x1 = 10 ; data-> x2 = 20.3 ; data-> car .drive();

16.Shared Memory 16 A Structure template used by each process can create a ‘plan’ or ‘blue print’ of the data which can be mapped or overlaid onto a blank block of memory that forms the datapool. Of course all processes must use the same template typically maintained within a header file Process B maintains a pointer to the datapool struct Pool { int joe ; char fred ; char array[256] ; float result ; } ; struct Pool *my_ptr; Data Pool Stored in Memory Shared Memory Process A maintains a pointer to the datapool struct Pool { int joe ; char fred ; char array[256] ; float result ; } ; Structure Template mapping/overlaying data for Process A onto datapool struct Pool *my_ptr; Structure Template mapping/overlaying data for Process B onto datapool

17.IPC: Shared Memory Shared Memory 17 template < typename T > class shared_object : private shared_memory { public : shared_object( const std :: string &name, bool readonly = false ); // can access as if it was a pointer to the type itself T & operator *(); T * operator ->(); T *get(); // gets pointer to underlying object bool unlink(); // unlinks name }; To facilitate fixed layouts, we introduce a new class in the CPEN 333 library:

18.IPC: Shared Memory Shared Memory 18 cpen333 :: process :: shared_memory memory( "big_memory_block" , sizeof ( MemoryLayout )); MemoryLayout * data = ( MemoryLayout *)memory.get(); data-> x1 = 10 ; data-> x2 = 20.3 ; data-> car .drive(); cpen333 :: process :: shared_object < MemoryLayout > memory( "big_memory_block" ); memory-> x1 = 10 ; memory-> x2 = 20.3 ; memory-> car .drive(); VS

19.IPC: Shared Memory Shared Memory 19 Allows any number or processes to access memory Any process can read/write to any part of memory block (i.e. random access ) There is no built-in synchronization ! Simultaneous writes lead to data races, must be solved using… Shared memory objects are extremely useful when multiple processes are running on the same machine, have access to the same hardware resources and operating system kernel. They can not be used in distributed systems/network environment.

20.Activity: Shared Memory Initialization Shared Memory 20 Who got there first? When requesting shared memory from the OS, a new memory block is allocated and returned, without any consideration of what kind of data it will hold (think: malloc ). On most systems, the memory contents are initialized to zero. Let’s say you want to initialize the data? How can you tell which process was the first to arrive?