I use boost::interprocess::managed_shared_memory to load a data structure in shared memory. I need to pin the shared memory segment into physical memory (for example similar to system call mlock for mapped files).
In linux, sooner or later my data structure gets swapped out of physical memory. In my case this incurs a forbidding cost for the next process accessing the structure, after it has been swapped out.
Is there any way to pin shared memory into physical memory? I am interested in any solution, even if it means that I cannot use boost::interprocess.
Using basic_managed_xsi_shared_memory (apparently available since boost 1.46), you can access the underlying shmid (from the get_shmid member) which should allow you to control the shmid using shmctl. With shmctl you can prevent the swapping of shared memory pages by applying the SHM_LOCK command to the shmid.
Other types of locking (which you refer to as 'pinning'), such as locking memory mapped files into memory, can be realized by supplying return values obtained from mapped_region's get_address and get_size member functions to the mlock command.
Related
Process A created a shared memory '1234' using shmget . After this , Process A attaches the memory to itself using shmat.
Process B also attaches shared memory corresponding to '1234' to itself using shmat.
Now what does "attach" mean exactly ? Are there two copies of the same memory existing ? If not , then where exactly is this memory existing ?
Every process has its own virtual memory space. To simplify things a bit, you can imagine that a process has all possible memory addresses 0x00000000..0xffffffff available for itself. One consequence of this is that a process can not use memory allocated to any other process – this is absolutely essential for both stability and security.
Behind the scenes, kernel manages allocations of all processes and maps them to physical memory, making sure they don't overlap. Of course, not all addresses are in fact mapped, only those that are being used. This is done by means of pages, and with the help of memory-mapping unit in the CPU hardware.
Creating shared memory (shmget) allocates a chunk of memory that does not belong to any particular process. It just sits there. From the kernel's point of view, it doesn't matter who uses it. So a process has to request access to it – that's the role of shmat. By doing that, kernel will map the shared memory into process' virtual memory space. This way, the process can read and write it. Because it's the same memory, all processes who have "attached" to it see the same contents. Any change a process makes is visible to other processes as well.
I was reading OS from Galvin and just had a doubt, how to implement memory protection if the system does not supports virtual memory ? I mean how processes can be given protected address spaces ?
Any new concept or explaination would be awesome...
Memory protection on Wikipedia shows different methods of memory protection, you should go through that.
If there is no support of virtual-memory, the concept of Protection keys method can be used.
Reading it :
A memory protection key (MPK) mechanism divides physical memory up
into blocks of a particular size (e.g., 4 kiB), each of which has an
associated numerical value called a protection key. Each process also
has a protection key value associated with it. On a memory access the
hardware checks that the current process's protection key matches the
value associated with the memory block being accessed; if not, an
exception occurs.
If you want to understand operating systems, use Galvin to line your cat box and nothing else.
The first key to understanding this problem is to understand the different between logical memory and virtual memory. Sadly, much process and OS documentation conflates the two terms.
Page tables define a continuous, linear, logical address space that maps pages to non-continuous page frames. => Logical memory.
Virtual memory is the process of a using secondary storage (disk) when a page table entry does not map to a physical page frame.
These are two closely related concepts. Virtual memory requires logical memory BUT logical memory does not require virtual memory.
In the latter case, the OS does not use secondary storage to simulate physical memory. When a process accesses a logical page, it must be mapped to a physical page frame, otherwise there is an error (and not a page fault, as in virtual memory).
In the pre-virtual memory days, things were done entirely differently. Then entire processes were swapped in and out (why in Eunuchs, the page file is called the swap partition).This was done using read/write to disk or mapping registers. In those days the address spaces were 64K bytes or smaller so writing a process to disk was not as onerous as it might seem.
In such systems, you got your own 64K or so memory and simply could not access beyond that to get to another process's memory.
I've always known that main memory caches data read from files on disk, but I have trouble reconciling this with the typical memory usage of a program, as shown in this diagram:
If I use fread or fgetl on a very large file 2010Stats.txt, on which segment of the above diagram does memory cache data from disk?
That's the address-space of your process. Each process has its own virtual memory address-space. Unless you mmap a file, its data only appears in your process's memory when copied there by a read system call or equivalent. (C stdio / iostream functions will be implemented on top of system calls like that.)
The disk-cache is managed by the OS kernel, which has to keep track of how the physical pages of memory are used, as well the virtual address mappings of every process.
What is difference between kmem_cache_alloc and kmalloc() in kernel memory allocation? which one is used when?
Kmalloc - allocates contiguous region from the physical memory. But keep in mind, allocating and free'ing memory is a lot of work.
Kmem_cache_alloc - Here, your process keeps some copies of the some pre-defined size objects pre-allocated. Say you have struct that you know you will be requiring very frequently, so instead of allocating it from the main memory (kmalloc) when you need it, you already keep multiple copies of it allocated & when you want it, it returns the address of the block already allocated (saves a lot of time). Similarly, when you free it, you don't give it back, it actually isn't free'd, it goes back to the allocated pool so that if some process again asks for it, you can return this address of the already allocated struct.
kmalloc: It uses the generic slab caches available to any kernel code. so your module will share slab cache with other components in kernel.
kmem_cache_alloc: It will allocate objects from a dedicated slab cache created by kmem_cache_create. If you specifically want a better slab cache management dedicated to your module only, that too for a specific type of objects, use kmem_cache_create followed by kmem_cache_alloc. USB/SCSI drivers use this. kmem_cache_create takes sizeof your object you want to create slab of, a name which appears in /proc/slabinfo and flags to govern behavior of your slab cache.
Ref: https://www.mail-archive.com/kernelnewbies#nl.linux.org/msg13191.html & LDD
I was wondering whether there is any reasonably portable way to take existing, unshared heap memory and to convert it into shared memory. The usage case is a block of memory which is too large for me to want to copy it unnecessarily (i.e. into a new shared memory segment) and which is allocated by routines out of my control. The primary target is *nix/POSIX, but I would also be interested to know if it can be done on Windows.
Many *nixe have Plan-9's procfs which allows to open read a process's memory by inspecting /proc/{pid}/mem
http://en.wikipedia.org/wiki/Procfs
You tell the other process your pid, size and the base address and it can simply read the data (or mmap the region in its own address space)
EDIT:: Apparently you can't open /proc/{pid}/mem without a prior ptrace(), so this is basically worthless.
Under most *nixes, ptrace(2) allows to attach to a process and read its memory.
The ptrace method does not work on OSX, you need more magic there:
http://www.voidzone.org/readprocessmemory-and-writeprocessmemory-on-os-x/
What you need under Windows is the function ReadProcessMemory
.
Googling "What is ReadProcessMemory for $OSNAME" seems to return comprehensive result sets.
You can try using mmap() with MAP_FIXED flag and address of your unshared memory (allocated from heap). However, if you provide mmap() with own pointer then it is constrained to be aligned and sized according to the size of memory page (may be requested by sysconf()) since mapping is only available for the whole page.