Processes and the Memory Manager

Memory-related work done by <#2013#> fork()<#2013#>: The processes end up sharing their code and data segments (although they have separate local descriptor tables, the entries point to the same segments). The stack and data pages will be copied when the parent or child writes to them (copy-on-write). Memory-related work done by <#2030#> exec()<#2030#>: Interrupts and traps are handled within the context of the current task. In particular, the page directory of the current process is used in address translation. The segments, however, are kernel segments so that all linear addresses point into kernel memory. For example, assume a user process invokes a system call and the kernel wants to access a variable at address 0x01. The linear address is 0xc0000001 (using kernel segments) and the physical address is 0x01. The later is because the process' page directory maps this range exactly as <#2045#> page_pg_dir<#2045#>. The kernel space (0xc0000000 + <#2046#> high_memory<#2046#>) is mapped by the kernel page tables which are themselves part of the RESERVED memory. They are therefore shared by all processes. During a fork <#2047#> copy_page_tables()<#2047#> treats RESERVED page tables differently. It sets pointers in the process page directories to point to kernel page tables and does not actually allocate new page tables as it does normally. As an example the <#2048#> kernel_stack_page<#2048#> (which sits somewhere in the kernel space) does not need an associated <#2049#> page_table<#2049#> allocated in the process' <#2050#> pg_dir<#2050#> to map it. The interrupt instruction sets the stack pointer and stack segment from the privilege 0 values saved in the tss of the current task. Note that the kernel stack is a really fragmented object~--- it's not a single object, but rather a bunch of stack frames each allocated when a process is created, and released when it exits. The kernel stack should never grow so rapidly within a process context that it extends below the current frame.