How Can a Process Try to Access Other Process's Memory in Linux Virtual Memory System

How can a process try to access other process's memory in Linux virtual memory system

Unless specifically arranged, there should be no virtual address one process can access that will modify memory assigned to another process.

How does the kernel access the memory of other processes?

What are "other processes" in this case?

If a thread is executing and it goes to the kernel for whatever reason and the kernel wants to read its memory, it can "just" do that on architectures where both userspace and kernelspace are mapped into one giant address space. In particular this is the case on x86.

Typically the kernel does not go around accessing memory mapped by a thread different than the one which switched into the kernel.

If such access is needed, the kernel walks the relevant page table "by hand". It finds what physical page is needed and just maps it so it can read. It most certainly does not switch page tables for this purpose.

As a fun fact, since the address space on x86-64 is so vast (256TB) compared to physically installable memroy, the entire physical memory is always mapped. Thus on this architecture the kernel just computes where the relevant page is within this area.

In virtual memory, can two different processes have the same address?

1)

  • Same physical memory address at the same time: NO
  • Same virtual memory address at the same time: YES (each one maps to differnet physical address, or swap space)

2) I think the debuggers don't access directly the other process debugged but communicates with the runtime in the debugged process to do that changes.

That said, maybe the OS or processor instructions provide access/modify to other's memory access if you have the right. That doesn't mean it has the SAME address, it only says process 1 can say "access memory @address1 in Process2". Someone (processor / OS / runtime) will do that for process 1.

how to access memory allocated to different process?

First and foremost, let me say that in modern operating systems, the address values that your program sees (like that 0x00402000) are not physical addresses. They are virtual addresses, they're private to the owning process (i. e. make no sense or mean something else in other processes), and are mapped to physical addresses via a CPU-based mechanism ("the paging unit") that only OS has control over.

If you want to share a variable between different processes, there's a mechanism called shared memory. Read up on it. The relevant APIs are CreateFileMapping with the the first parameter being INVALID_HANDLE_VALUE, MapViewOfFile, OpenFileMapping. There are other ways of interprocess communication, too.

If you want to read process' memory without that process' explicit cooperation, you need to read up on debugging API. This is a much trickier job than using shared memory.

What you've coded, by the way, is a classic undefined behavior.

How does each process's private address space gets maped to physical address?

That is the job of the MMU (Memory Management Unit), or one of the jobs. Process A's 0x400000 might be physical address 0x12300000 and Process B's 0x400000 might be physical address 0x32100000 for example. Basically when process A is running there is a mmu table for that core it is running on that replaces 0x004xxxxx with 0x123xxxxx for example in a simplified way. It is a direct address bit replacement, the size of the space can vary both one mmu may have multiple block sizes as well as one architectures mmu chips mmu may vary from another. It could be a case of 0x0040 becomes 0x1230 and 0x0041 becomes 0x1231 and so on.

It can also be that 0x0040 becomes 0x1111 and 0x0041 becomes 0x2123 and 0x0042 becomes 0x1312. For each block size in the mmu you can have a different address replacement from virtual to physical. Likewise for each block in the mmu you can have different protection and other features. For code the processor may have a read only feature, it should have at least a basic cache enable/disable feature as code you want to cache but some data areas you may not. And then address spaces that you want to trap the process from accessing so marking the rest of the address space as invalid.

Assume for understanding purposes there is one size of block and some table (this table might live at physical address 0x40010000)

virtual     physical
...
0x00400000 0x1230000
0x00410000 0x1231000
0x00420000 0x1232000
...

for process A and this table was created by the operating system at some physical address.

If/when that core switches to process B, then ideally a single register re-directs the mmu to some other physical address for the table (this physical table might live at 0x40020000)

...
0x00400000 0x32100000
0x00410000 0x32110000
0x00420000 0x32120000
...

As an example.

So you can link every program for the same address space, but physically they are in separate memory that doesn't interfere with each other.

And if process A and process B are in different cores and/or behind different MMUs then they would still have their own mmu table in front of them but could concurrently run.

Now I don't know the x86 implementation and expect that over the years different chips had different mmus, but, some architecture designs the mmu is per core so one process per core at a time one mmu table for that core at a time. If the mmu is further down and there are multiple cores per mmu then there is going to be some sort of process ID such that the access still lands on a unique set of entries per process.

MMUs these days make this virtual to physical mapping happen, they cover caching or not, and protection of address spaces to keep the application from wandering about memory. But if you think about it this also greatly helps memory allocation and management. Let's say for example in my made up table above the mmu actually does operate on 64K byte sections. if I want to allocate 256Kbytes of data, the operating system doesn't need to find a linear 256Kbytes, It only needs to find four 64Kbyte chunks, anywhere. It doesn't need to try to move memory around like the way old days or copy it somewhere and put it back before whoever owned that memory before wanted to access it etc.

0x00500000 0x11210000
0x00510000 0x31230000
0x00520000 0x12120000
0x00530000 0x43210000

To the process that looks like 256K of linear memory, but in reality it is smaller chunks nowhere near each other.

Pointer to a memory location of another process

The whole point of processes and memory management in the form they appear in modern OS's is that you cannot have a pointer from one process to another. Their memory is separated and one process cannot usually see the memory of another memory. To each process it looks like it has almost all the memory of the system available to it, as if there were only this one process (and the kernel, which might map stuff into the process' memory region).

The exception is shared memory: if both processes share a shared memory region and both processes have the access rights to modify the region, then yes, one process can modify the memory of the other process (but only within the bounds of that shared memory region).

IIRC, it works like this on the lowest level: the kernel manages a list of memory regions for each process. These regions might map to physical memory. If a region isn't mapped to physical memory and the process tries to access the region, the CPU signals the kernel to make it available (for example by loading its content from a swap file/partition). If two processes use shared memory, for both processes these regions would map to the same physical memory location (or swap file location). You might want to read about MMU and virtual memory.



Related Topics



Leave a reply



Submit