I've read a couple things about memory management/virtual memory and I need a little more details on one important point.
If I compile a program and it does an access to a hard-coded address without any allocation calls, when I run it the process gets an error signal, terminated by signal SIGSEGV (Address boundary error)
.
Example program:
#include <stdio.h>
void main()
{
int * x = 0x1312;
printf("%d\n", *x);
}
Compiled with mere:
$ gcc accessing-random-address.c -o random-address-access
Here I don't get what exactly happens when a program is turned into a process. The compiled program is all-machine-code, isn't it? The address access should look like mv (0x1312) regN
. If this code runs -- how could the OS detect that the code accesses a memory outside of its' memory range?
So, my question is -- what mechanism is used in Linux/Unixes to catch such rogue memory accesses and send the signal to the process? At what moment is it done?
In fact, the same question applies to the way how a program is converted to a process. If the program has been compiled for some architecture -- it should use the physical addresses and registers of the processor. But the process uses the virtual memory, with page-tables etc.
So, is there some intermediate executable Linux-specific format, which gcc
compiles to? And this format is somehow converted to real machine code when the program is loaded into memory as a process? And then in the real machine code the memory access is not just mv A B
but some procedure with kernel's page tables, page numbers and offsets?
PS
Probably this question would be clarified with more reading. But I would like to have this knowledge upfront -- so that "the main picture" is complete before getting other details.