问题
I have a C++ application that allocates shared memory on a Linux system via shmget(2). The data that I store in the shared memory grows periodically, and I'd like to resize the shared memory in a way analogous to the way realloc() grows regular memory. Is there a way to do this? I found a doc on IBM's site that mentions a SHM_SIZE command, but the Linux and BSD manpages do not have it, even in the Linux-specific sections.
回答1:
Simple answer: there is no easy way.
The reasons are pretty logical. Shared memory is being attached to virtual space of every process individually. Each process has it's own virtuall address space. Each process is free to attach the segment at any (not literally, alignment sets some restrictions) arbitrary address. How can system guarantee that, let's say by extending area by 4MiB, every 'user' of this segment will be able to fit bigget block at the same starting address where the smaller segment previously was?
But you should not give up! You can be creative. You can come up with the idea of having one header segment, where you store information about real payload segment. You can make every process to obey some rules as for example: reattach payload segment when its id, as described somewhere in header segment, does not match the known one.
The advice: I suspect you know this, but never keep pointers to data within shared region, only offset.
I hope you'll have some use of my gibberish.
回答2:
It seems for me that you can write your own memory manager for your purpose. The conception is quite simple:
- You have a shared memory block which size is
N
bytes; - Allocate new block of shared memory with
2*N
size; - Copy memory from one block to another;
- Free the old shared memory block;
- Wrap the #2-4 into some routine and use it;
I'm afraid we have nothing more to do with that. This is how std::vector
is implemented. And void *realloc()
in most of cases will return you the pointer to the new block of memory (but not to the extended old block).
回答3:
It seems to me that the function mremap was implemented to perform what you want. You just have to precise in argument the old size and the new one of the shared memory segment. And if you add the flag MREMAP_MAYMOV, it allows to move the shared memory segment if needed (i.e if not enough free space just after the old shared memory segment).
Look at the manpage : http://man7.org/linux/man-pages/man2/mremap.2.html.
来源:https://stackoverflow.com/questions/16423789/can-i-resize-linux-shared-memory-with-shmctl