2013年8月25日 星期日

Linux memory layout

每一個user process看到的vitrual memory共有4G(32 bit machine)

其中通常切成3G:1G
0x00000000-0xbfffffff: user process(3GB)
0xc0000000-0xffffffff: kernel space (1GB)

而user process(3G)是每支user process不同的,甚至每支user thread也是不同
                                                                                    (因為thread不共享stack)

而kernel space那1G勒?
我很好奇以下這點:
   每支kernel thread看到的kernel space memory都是一樣的嗎?  如果是一樣,那kernel thread 之間就是share memory了!

目前的猜測是一樣的,因為資料上都說user process所看到user space那3G都不相同,這樣講的意思應該就是kernel space那1G每個user process看到的都相同,也就代表kernel只有一份memory layout了(user space看的到那1G只是知道有那1G,但實際上是沒辦法access的)

以下看了Linux Device Driver第15張Memory Mapping and DMA
http://lwn.net/Kernel/LDD3/
做出以下筆記

Memory types:
1. User virtual address - These are the regular addresses seen by user-space programs.
2. Physical address - The addresses used between the processor and the system’s memory.
3. Bus address - The addresses used between peripheral buses and memory.
(same as physical address often, different in using IOMMU)
4. Kernel logical address - These make up the normal address space of the kernel. These addresses map some portion (perhaps all) of main memory and are often treated as if they were physical addresses. On most architectures, logical addresses and their associated physical addresses differ only by a constant offset.
5. Kernel virtual address - Kernel virtual addresses are similar to logical addresses in that they are a map-ping from a kernel-space address to a physical address. Kernel virtual addresses do not necessarily have the linear, one-to-one mapping to physical addresses that characterize the logical address space, however.

If you have a logical address, the macro __pa( ) (defined in <asm/page.h>) returns its associated physical address. Physical addresses can be mapped back to logical addresses with __va( ), but only for low-memory pages.



一個很重大的突破:
在kernel space那1G之中,還有分成high memory, low memory
Low memory用來存kernel的code, data
High memory就是用來當kernel要access超過1G的memory時候用的
這本書裡面會一直講logical memory,而我把logical memory就想成他在講low memory
而講kernel virtual memory就會包含low&high memory



像這個function 
void *kmap(struct page *page); (以下LDD課文)
kmap returns a kernel virtual address for any page in the system. For low-mem-
ory pages, it just returns the logical address of the page; for high-memory pages,
kmap creates a special mapping in a dedicated part of the kernel address space.

Reference : http://kneuro.net/linux-mm/index.php?file=kmap.html
The HIGHMEM patches allow the kernel to use more than 1G of memory by mapping the additional pages into the high part of the kernel address space just below 4GB as necessary. They also allow high-memory pages to be mapped into user process address space.
kmap() is called with a page struct* argument: the page frame of a page to map into kernel space. This can be a normal or HIGHMEM page; in the former case kmap() simply returns the direct-mapped address. For HIGHMEM pages, we search for an unused entry in the kmap pagetables that were allocated at boot time; this search is done by simply examining the pkmap_count entries in order, looking for a zero entry. If none is found, we sleep waiting for another process to unmap a page. When we find an unused entry, we insert the physical page address of the page we want to map, increment the pkmap_count reference count for the pagetable entry, and return the virtual address to the caller. We also update the page->virtual for the page struct to indicate the mapped address. 

綜合以上加上自已的想法,我覺得kmap比較合理的解釋應該是:
 當丟入的是low memory page時就直接回傳該page對應的logical memory
 而丟入非low memory page時(像是user space的page),他就會去找kmap pagetable找尋沒在 使用的entry,並在這個entry做此丟入page的mapping,並回傳此kmap entry的kernel virtual address
這樣應該比較合理,因為high memory的用處就是讓kernel可以摸到1G之外的空間,所以kmap應該要是可以吃user space page並讓kernel從kernel space map到他並access

0 意見:

張貼留言