下面的代碼就是這個(gè)時(shí)候內(nèi)核代碼,






























它完成了內(nèi)存的分頁、分配工作。其中調(diào)用了其他的代碼,且看他是如何工作的:
ROOT_DEV = ORIG_ROOT_DEV; /* #define ORIG_ROOT_DEV (*(unsigned short *)0x901FC) */
drive_info = DRIVE_INFO; /* (*(struct drive_info *)0x90080) */
他們的意思非常想近
0x901FC 和 0x90080 所在地址開始長度unsigned short與struct drive_info長度的內(nèi)存空間內(nèi)容,已在前面在系統(tǒng)引導(dǎo)代碼/boot/setup.s 中已做了設(shè)置
具體是:
0x90080地址開始存放的是兩個(gè)硬盤參數(shù)表,0x90080~0x9008f放了第一個(gè)硬盤的參數(shù);0x90090~0x9009f存放了第二個(gè)硬盤的參數(shù)表,具體代碼






















#define EXT_MEM_K (*(unsigned short *)0x90002)
其中0x90002的內(nèi)容也是在Setup.s設(shè)置好的








具體實(shí)現(xiàn)還得參考一下setup.s在此處的上下文,由于這并非該文重點(diǎn)就講到說到這里,其實(shí)大家在這只需要知道,EXT_MEM_K是當(dāng)前物理內(nèi)存的1M以后的擴(kuò)展內(nèi)存就可以了。
(如果你對(duì)(*(unsigned short *)0x90002) 不了解什么意思 那么請(qǐng)參考前一篇指針文章。)
memory_end = (1 << 20) + (EXT_MEM_K << 10); /*后面會(huì)看到內(nèi)核的將占用1M的空間*/
可以知道 memory_end = 1024(K) + EXT_MEM_K(K) /*注意單位*/
memory_end &= 0xfffff000; /*因?yàn)橐院蟮牟僮鞫际菍?duì)整的4空間當(dāng)一個(gè)整體進(jìn)行的*/
忽略小于等于4K大小的內(nèi)存,也就是說經(jīng)過這個(gè)設(shè)置,linux內(nèi)存的每一頁大小為4K。
也許有人搞不清楚4K怎么算得?
上面將memory_end(以二進(jìn)制方式)底上的12位(0xfff)全設(shè)0,2的12次方bits恰好是4K。
if (memory_end > 16 * 1024 * 1024)
memory_end = 16 * 1024 * 1024;
這里設(shè)置內(nèi)存大大小最終不超過16M
也許有的人會(huì)怎么想:不是說總內(nèi)存可以用到4G嗎?這里怎么~~~,且看下面
if (memory_end > 12 * 1024 * 1024) /*如果內(nèi)存>12Mb,則設(shè)置緩沖區(qū)末端=4Mb*/
buffer_memory_end = 4 * 1024 * 1024;
else if (memory_end > 6 * 1024 * 1024) /* 否則如果內(nèi)存>6Mb,則設(shè)置緩沖區(qū)末端=2Mb*/
buffer_memory_end = 2 * 1024 * 1024;
else
buffer_memory_end = 1 * 1024 * 1024; /* 緩沖區(qū)地址不小于1M*/
接下來根據(jù)memory_end的大小設(shè)置緩沖區(qū)大小,根據(jù)前面情況如果內(nèi)存比較到那么緩沖區(qū)就搞大點(diǎn),小的話就只能省點(diǎn)用了。
main_memory_start = buffer_memory_end;
將主內(nèi)存起始地址 = 緩沖區(qū)的結(jié)束地址
#ifdef RAMDISK /* 如果定義了虛擬盤,則主內(nèi)存將減少。*/
main_memory_start += rd_init (main_memory_start, RAMDISK * 1024);
#endif
這個(gè)時(shí)候還要看看有沒有分配虛擬盤,我在最前面的代碼加了一個(gè)define在這里得到發(fā)揮作用了。
前面對(duì) rd_init這個(gè)函數(shù)做了如下定義 extern long rd_init (long mem_start, int length);
它的作用是:虛擬盤初始化,該函數(shù)在“kernel/blk_drv/ramdisk.c”中實(shí)現(xiàn)
















可以在該目錄下的 blk.h 中找到如下信息
#define NR_BLK_DEV 7 / 塊設(shè)備的數(shù)量。*/
extern struct blk_dev_struct blk_dev[NR_BLK_DEV]; /* 塊設(shè)備數(shù)組,每種塊設(shè)備占用一項(xiàng)。*/
/* 塊設(shè)備結(jié)構(gòu)。*/
struct blk_dev_struct
{
void (*request_fn) (void); /* 請(qǐng)求操作的函數(shù)指針。*/
struct request *current_request; /* 請(qǐng)求信息結(jié)構(gòu)。*/
};
那么這個(gè)地方的函數(shù)指針指向誰呢?
#define DEVICE_REQUEST do_fd_request /* 設(shè)備請(qǐng)求函數(shù)do_fd_request()。*/
那do_fd_request函數(shù)的實(shí)現(xiàn)在什么地方呢?
它在/blk_dev/Ramdisk.c中




































(其中sector << 9 表示sector * 512這個(gè)問題在我前前一篇文章已做了詳細(xì)的講解)
代碼中的INIT_REQUEST在blk_dev/blk.h中被 定義初始化請(qǐng)求宏。















對(duì)于這個(gè)do_rd_request涉及到對(duì)塊設(shè)備的操作,這里不做詳細(xì)講解。大家只要知道,這個(gè)函數(shù)對(duì)rd_init這個(gè)函數(shù)是對(duì)ramdisk進(jìn)行初始化便可。
終于快完了,也許你會(huì)感覺看得很累,哎!我寫得更累

mem_init (main_memory_start, memory_end);
終于到內(nèi)存初始化了,嘿嘿
假設(shè)我們現(xiàn)在的內(nèi)存比較到,擴(kuò)展內(nèi)存超過16M
經(jīng)過前面的操作我們大概知道內(nèi)存是這樣的
______ 16M(在該版本的linux最多支持16M內(nèi)存,多余的內(nèi)存將被視而不見)
| . | 前面的問題在這里得到解釋
| . |
|主內(nèi)存|
|———| 4M+32K(前面我定義了32)
|虛擬盤|
|———| 4M
|高速緩|
|沖區(qū) |
|———| 1M(其實(shí)內(nèi)核大小之后640K)
|內(nèi)核 |
——— 0M
mem_init (main_memory_start, memory_end);最關(guān)鍵的函數(shù)出來了,
該函數(shù)在mm/memory.c中被實(shí)現(xiàn),實(shí)現(xiàn)主內(nèi)存初始化;














static long HIGH_MEMORY = 0; /* 全局變量,存放實(shí)際物理內(nèi)存最高端地址16M。在該版本的linux最多支持16M內(nèi)存,多余的內(nèi)存將被視而不見*/
接下來的for循環(huán)用到如下定義:
#define PAGING_MEMORY (15*1024*1024) /*除內(nèi)核占用的那1M內(nèi)存,其他的內(nèi)存都會(huì)被分頁,中共為15MB(前面已假設(shè)內(nèi)存大于16M)。即,被分頁的內(nèi)存最多15M(這里的15M指的是緩沖區(qū)+主內(nèi)存)*/
#define PAGING_PAGES (PAGING_MEMORY>>12) /* 偏移之后恰好為分頁后的物理內(nèi)存頁數(shù)*/
/*內(nèi)存映射字節(jié)圖(1 字節(jié)代表1 頁內(nèi)存),每個(gè)頁面對(duì)應(yīng)的字節(jié)用于標(biāo)志頁面當(dāng)前被引用(占用)次數(shù)。*/
static unsigned char mem_map[PAGING_PAGES] = { 0, };
#define USED 100 /* 頁面被占用標(biāo)志*/
#define LOW_MEM 0x100000 /* 低端內(nèi)核內(nèi)存空間(1MB)。*/
#define MAP_NR(addr) (((addr)-LOW_MEM)>>12) /* 這里定義了一個(gè)函數(shù),指定內(nèi)存地址映射為頁號(hào) i。*/
end_mem -= start_mem; /* 再計(jì)算可分頁處理的內(nèi)存空間。*/
end_mem >>= 12; /* 從而計(jì)算出可用于分頁處理的頁面數(shù)。*/
while (end_mem-- > 0) /* 最后將這些可用頁面對(duì)應(yīng)的頁面映射數(shù)組清零。*/
mem_map[i++] = 0;
到這里內(nèi)存初始化真正完成,讓我們回顧一個(gè)整個(gè)過程吧!
設(shè)置緩沖區(qū)地址(不小與1M)==> 如果定義了ramdisk那么設(shè)置它,并將該部分內(nèi)存的值全搞成'\0' ==>將主內(nèi)存設(shè)置在它后面,然后對(duì)除內(nèi)核(也許緩沖區(qū)在此內(nèi)存區(qū)域中)占用的那空間進(jìn)行分頁(每頁4K),再對(duì)內(nèi)存內(nèi)存映射字節(jié)圖進(jìn)行初始化。
也許你現(xiàn)在在想,我該找出去散下心,我快瘋了!!! 呵呵 慢慢來

地震讓大伙知道:居安思危,才是生存之道。
