is shared memory on heap only? - c++

I understand that stack memory can only be shared by threads within same process.
In Inter-Process Communication, processes can share same segment of memory via shmget() system call.
What can this shared memory segment be? a heap or anything else?
Update:
I came up with this question after browsing questions about difference between stack and heap memory. Could heap memory be the shared memory segment via shmget()? That is, could heap memory be shared among multiple processes?
Update II:
Does a parent process share the same heap with its child process? I find something online:
"The heap, code and library regions of the parent are shared by the child. A new stack is allocated to the child and the parent's stack is copied into the child's stack."
Does this mean same heap is shared between difference processes?
"Also there might be a global heap (look at Win32 GlobalAlloc() family functions for example) which is shared between processes, persists for the system runtime and indeed can be used for interprocess communications." reference: Is heap memory per-process? (or) Common memory location shared by different processes?

In the Unix operating system, shared memory lives outside of any individual process space. By using shmat you basically get a pointer to some space that the kernel has allocated for you. These spaces can be shared between process and attached to by any number of processes. Like a file you can set permissions so that not every process can see and/or attach to the memory.
In this context shared memory is not a traditional stack or heap - it's a chunk of memory that the kernel gives you access to (assuming the correct permissions). Again, it lives outside of any one process space as the kernel manages it. Usually the memory remains in use even if no processes are attached to it. In Linux, an ipcs -m shows these segments.

Related

How to programmatically differentiate objects created on heap and stack section of memory

Suppose I want to keep track of all the objects created in a C++ program.
In the stack section of memory (Object obj;)
In heap section of memory (dynamic allocation using new)
Is there any way I can know how many objects are in the stack and how many are in heap memory? The constructor will be called in both cases so it doesn't help.
See:
What and where are the stack and heap?
In particular:
"The OS allocates the stack for each system-level thread when the
thread is created. Typically the OS is called by the language runtime
to allocate the heap for the application."
and...
...while the stack is allocated by the OS when the process starts
(assuming the existence of an OS), it is maintained inline by the
program. This is another reason the stack is faster, as well - push
and pop operations are typically one machine instruction, and modern
machines can do at least 3 of them in one cycle, whereas allocating or
freeing heap involves calling into OS code.
Thus, I believe the answer to your question is that you'd need full root access to the operating system's internal memory paging system to keep track of all objects (particularly on the heap). As far as I know, all garbage collection systems use a reference count approach to manage heap memory allocation and don't directly access the operating system's heap allocation records. There are very good security reasons for this I'm sure.

Is shared virtual memory used when multiple processes read a file using file pointer in Linux?

I wrote a C++ program which read a file using file pointer. And I need to run multiple process at the same time. Since the size of file can be huge (100MB~), to reduce memory usage in multiple processes, I think I need use shared memory. (For example IPC library like boost::interprocess::shared_memory_object)
But does it really need? Because I think if multiple processes read same file, then virtual memory of each processes mapped to same physical memory of file thru page table.
I read a Linux doc and they said,
Shared Virtual Memory
Although virtual memory allows processes to have separate (virtual)
address spaces, there are times when you need processes to share
memory. For example there could be several processes in the system
running the bash command shell. Rather than have several copies of
bash, one in each processes virtual address space, it is better to
have only one copy in physical memory and all of the processes running
bash share it. Dynamic libraries are another common example of
executing code shared between several processes. Shared memory can
also be used as an Inter Process Communication (IPC) mechanism, with
two or more processes exchanging information via memory common to all
of them. Linux supports the Unix TM System V shared memory IPC.
Also, wiki said,
In computer software, shared memory is either
a method of inter-process communication (IPC), i.e. a way of exchanging data between programs running at the same time. One process
will create an area in RAM which other processes can access, or
a method of conserving memory space by directing accesses to what would ordinarily be copies of a piece of data to a single instance
instead, by using virtual memory mappings or with explicit support of
the program in question. This is most often used for shared libraries
and for XIP.
Therefore, what I really curious is that does shared virtual memory supported by OS level or not?
Thanks in advance.
Regarding your first question - if you want your data to be accessible by multiple processes without duplication you'll definitely need some kind of a shared storage.
In C++ I'd surely use boost's shared_memory_object. That's a valid option to share (large) data among processes and it has good documentation with examples (http://www.boost.org/doc/libs/1_55_0/doc/html/interprocess/sharedmemorybetweenprocesses.html).
Using mmap() is a more low-level approach usually used in C. To use it as an IPC you'll have to make the mapped region shared. From http://man7.org/linux/man-pages/man2/mmap.2.html:
MAP_SHARED
Share this mapping. Updates to the mapping are visible to
other processes that map this file, and are carried
through to the underlying file. The file may not actually
be updated until msync(2) or munmap() is called.
Also on that page there's an example of mapping a file to shared memory.
In either case there are at least two things to remember:
You need synchronization if there are multiple processes that modify the shared data.
You can't use pointers, only offsets from the beginning of the mapped region.
Here's an explanation from the boost docs:
If several processes map the same file/shared memory, the mapping address will be surely different in each process. Since each process might have used its address space in a different way (allocation of more or less dynamic memory, for example), there is no guarantee that the file/shared memory is going to be mapped in the same address.
If two processes map the same object in different addresses, this invalidates the use of pointers in that memory, since the pointer (which is an absolute address) would only make sense for the process that wrote it. The solution for this is to use offsets (distance) between objects instead of pointers: If two objects are placed in the same shared memory segment by one process, the address of each object will be different in another process but the distance between them (in bytes) will be the same.
Regarding the OS support - yes, shred memory is an OS specific feature.
In Linux mmap() is actually implemented in kernel and modules and can be used to transfer data between user and kernel-space.
Windows also has it's specifics:
Windows shared memory creation is a bit different from portable shared memory creation: the size of the segment must be specified when creating the object and can't be specified through truncate like with the shared memory object. Take in care that when the last process attached to a shared memory is destroyed the shared memory is destroyed so there is no persistency with native windows shared memory.
Your question doesn't make sense.
I think I need use shared memory. (For example IPC library like boost::interprocess::shared_memory_object).
If you use shared memroy, the memory is shared.
I think if multiple processes read same file, then virtual memory of each processes mapped to same physical memory of file thru page table.
Now you're talking about memory-mapped I/O. It isn't the same thing. However more probably it is what you need in this situation.

Is opening a shared memory multiple times bad in any way?

I have a class which opens a posix shared memory using shm_open. Now I have to create objects of this class multiple times (5-10 objects total), and that means the same shared memory is going to be opened that many times.
The shared memory has variable size, and can be from 1k to 500k.
The questions regarding this are :
1. Is this going to cause increased memory usage? (I do not see this happening, so my guess is no)
2. Is this going to cause bad performances when accessing shared memory?
3. Anything else that can go wrong?
The answer is on the page you linked shm_open to:
shm_open() creates and opens a new, or opens an existing, POSIX shared memory object. A POSIX shared memory object is in effect a handle which can be used by unrelated processes to mmap(2) the same region of shared memory.
To access a shared memory object, you need a handle to it. shm_open() can be used both to open (create) new, and reopen existing shared memory object. No memory increase nor bad performances occur when reopening an existing object.
It will not increase memory usage, however you use up handles each time you open a shared memory and you may run out. (Each process has a limit to the number of open handles.)
You need to manage access to the shared memory possibly using synchronization objects such as semaphores.
Mmap maps to a different base-address each time, so storing pointers pointing into shared memory is a bad idea.

Memory allocation - Common memory for a process tree

I have to write a code such that, it may create child process via Createprocess API.
Parent process in the process tree has to allocate the memory common to the total process tree, so that child process can access it.
Malloc, globalalloc does allocate memory within the scope for the process. However I could not extend it for the child process. Was there any APIs in Windows to allocate memory specific for a process tree. If not, Is there any API to allocate memory as a session image.
The way to share memory across processes under Windows is through memory-mapped files. Don't be thrown off by the word "file"; there doesn't have to be a file under the memory (other than the swap file).

Can Win32 "move" heap-allocated memory?

I have a .NET/native C++ application. Currently, the C++ code allocates memory on the default heap which persists for the life of the application. Basically, functions/commands are executed in the C++ which results in allocation/modification of the current persistent memory. I am investigating an approach for cancelling one of these functions/commands mid-execution. We have hundreds of these commands, and many are very complicated (legacy) code.
The brute-force approach that I am trying to avoid is modifying each and every command/function to check for the cancellation and do all the appropriate clean-up (freeing heap memory). I am investigating a multi-threaded approach in which an additional thread receives the cancellation request and terminates the command-execution thread. I would want all dynamic memory to be allocated on a "private heap" using HeapCreate() (Win32). This way, the private heap could be destroyed by the thread handling the cancellation request. However, if the command runs to completion, I need the dynamic memory to persist. In this case, I would like to do the logical equivalent of "moving" the private heap memory to the default/process heap without incurring the cost of an actual copy. Is this in any way possible? Does this even make sense?
Alternatively, I recognize that I could just have a new private heap for every command/function execution (each will be a new thread). The private heap could be destroyed if the command is cancelled, or it would survive if the command completes. Is there any problem with the number of heaps growing indefinitely? I know there is some overhead involved with each heap. What limitations might I run into?
I am running on Windows 7 64-bit with 8GB RAM (consider this the target platform). The application I am working with is about 1 million SLOC (half C++, half C#). I am looking for any experience/suggestions with private heap management, or just alternatives to my solution.
You might be better off with separate processes instead of separate threads:
use memory mapped files (ie not a file at all - just cross-processed shared memory)
killing a process is 'cleaner' than killing a thread
I think you can have the shared memory 'survive' the killing without a move - you map/unmap instead of move
although you might need to do some memory management on your own.
Anyhow, worth looking into. I was looking into using inter-process memory for a few other things, and it had some unusual properties (can recall all of it clearly, it was a while ago), and you might be able to take advantage of it.
Just an idea!
From MSDN's Heap Functions page:
"Memory allocated by HeapAlloc is not movable. The address returned by HeapAlloc is valid until the memory block is freed or reallocated; the memory block does not need to be locked."
Can you re-link the legacy apps against your own malloc() implementation? If so, you should be able to manage without modifying the rest of the code. Your custom malloc library can track allocated blocks by thread, and have a "FreeAllByThreadId() function which you call after killing the legacy function's thread. You could use private heaps inside the library.
An alternative to private heaps might be doing your own allocation from memory-mapped files. See "Creating Named Shared Memory." You create the shared memory while initializing the alloc library for the legacy thread. On success, map it into the main thread so your c# can access it; on termination, close it and it is released to the system.
Heap is a sort of big chunk of memory. It is a user-level memory manager. A heap is created by lower-level system memory calls (e.g., sbrk in Linux and VirtualAlloc in Windows). In a a heap, then you can request or return a small chunk of memory by malloc/new/free/delete. By default, a process has a single heap (unlike stack, all threads share a heap). But, you can have many heaps.
Is it possible to combine two heaps w/o copying? A heap is essentially a data structure that maintains a list of used and freed memory chunks. So, a heap should have a sort of bookkeeping data called meta data. Of course, this meta data is per heap. AFAIK, no heap manager supports a merge operation of two heaps. I had reviewed entire source code of malloc implementation in Linux glibc (Doug Lea's implementation), but no such operation. Windows Heap* functions are also implemented in a similar way. So, it is currently impossible to move or merge two separate heaps.
Is it possible to have many heaps? I don't think there should be a big problem to have many heaps. As I said before, a heap is just a data structure that keeps used/freed memory chunks. So, there should be some amount of overhead. But, it's not that severe. When you look at one of malloc implementation, there is malloc_state, which is a basic data structure for each heap. For example, you can create another heap by create_mspace (in Windows, it is HeapCreate), then you will get a new malloc state. It's not that big. So, if this tread-off (some heap overhead vs. implementation easiness) is fine, then you may go on.
If I were you, I'll try the way you describe. It makes sense to me. Having a lot of heap objects would not make a big overhead.
Also, it should be noted that technically moving memory regions is impossible. Pointers that pointed the moved memory region will result in dangling pointers.
p.s. Your problem seems like a transaction, especially Software Transactional Memory. A typical implementation of STM buffers pending memory writes, and then commits to the real system memory it the transaction had no conflict.
No. Memory cannot be moved between heaps.