����13-1 linux/mm/memory.c


  1 /*

  2  *  linux/mm/memory.c

  3  *

  4  *  (C) 1991  Linus Torvalds

  5  */

  6

  7 /*

  8  * demand-loading started 01.12.91 - seems it is high on the list of

  9  * things wanted, and it should be easy to implement. - Linus

 10  */

    /*

     * ��������Ǵ�91.12.1��ʼ��д�� - �ڳ�����Ʊ����ƺ�������Ҫ�ij���

     * ����Ӧ���Ǻ����ױ��Ƶ� - Linus

     */

 11

 12 /*

 13  * Ok, demand-loading was easy, shared pages a little bit tricker. Shared

 14  * pages started 02.12.91, seems to work. - Linus.

 15  *

 16  * Tested sharing by executing about 30 /bin/sh: under the old kernel it

 17  * would have taken more than the 6M I have free, but it worked well as

 18  * far as I could see.

 19  *

 20  * Also corrected some "invalidate()"s - I wasn't doing enough of them.

 21  */

    /*

     * OK����������DZȽ����ױ�д�ģ�������ҳ��ȴ��Ҫ�е㼼�ɡ�����ҳ�������

     * 91.12.2��ʼ��д�ģ������ܹ����� - Linus��

     *

     * ͨ��ִ�д�Լ30��/bin/sh�Թ������������˲��ԣ������ں˵�����Ҫռ�ö���

     * 6M���ڴ棬��Ŀǰȴ���á����ڿ��������úܺá�

     *

     * ��"invalidate()"����Ҳ���������� - ���ⷽ���һ����IJ�����

     */

 22

 23 /*

 24  * Real VM (paging to/from disk) started 18.12.91. Much more work and

 25  * thought has to go into this. Oh, well..

 26  * 19.12.91  -  works, somewhat. Sometimes I get faults, don't know why.

 27  *              Found it. Everything seems to work now.

 28  * 20.12.91  -  Ok, making the swap-device changeable like the root.

 29  */

    /*

     * 91.12.18��ʼ��д�����������ڴ����VM������ҳ�浽/�Ӵ��̣�����Ҫ�Դ�

     * ���Ǻܶಢ����Ҫ���ܶ๤�����Ǻǣ�Ҳֻ�������ˡ�

     * 91.12.19  -  ��ij�̶ֳ��Ͽ��Թ����ˣ�����ʱ���������֪����ô���¡�

     *              �ҵ������ˣ����ں���һ�ж��ܹ����ˡ�

     * 91.12.20  -  OK���ѽ����豸�޸ijɿɸ��ĵ��ˣ�������ļ��豸������

     */

 30

 31 #include <signal.h>       // �ź�ͷ�ļ��������źŷ��ų������źŽṹ���źź���ԭ�͡�

 32

 33 #include <asm/system.h>   // ϵͳͷ�ļ����������û��޸�������/�ж��ŵ�Ƕ����ꡣ

 34

 35 #include <linux/sched.h>  // ���ȳ���ͷ�ļ�����������ṹtask_struct������0�����ݡ�

 36 #include <linux/head.h>   // headͷ�ļ���������������ļ򵥽ṹ���ͼ���ѡ���������

 37 #include <linux/kernel.h> // �ں�ͷ�ļ�������һЩ�ں˳��ú�����ԭ�ζ��塣

 38

    // CODE_SPACE(addr) ((((addr)+0xfff)&~0xfff)<current->start_code+current->end_code)��

    // �ú������жϸ������Ե�ַ�Ƿ�λ�ڵ�ǰ���̵Ĵ�����У���(((addr)+4095)&~4095)������

    // ȡ�����Ե�ַaddr�����ڴ�ҳ���ĩ�˵�ַ���μ�265�С�

 39 #define CODE_SPACE(addr) ((((addr)+4095)&~4095) < \

 40 current->start_code + current->end_code)

 41

 42 unsigned long HIGH_MEMORY = 0;          // ȫ�ֱ��������ʵ�������ڴ���߶˵�ַ��

 43

    // ��from������1ҳ�ڴ浽to����4K�ֽڣ���

 44 #define copy_page(from,to) \

 45 __asm__("cld ; rep ; movsl"::"S" (from),"D" (to),"c" (1024):"cx","di","si")

 46

    // �����ڴ�ӳ���ֽ�ͼ��1�ֽڴ���1ҳ�ڴ棩��ÿ��ҳ���Ӧ���ֽ����ڱ�־ҳ�浱ǰ������

    // ��ռ�ã���������������ӳ��15Mb���ڴ�ռ䡣�ڳ�ʼ������mem_init()�У����ڲ�����

    // �����ڴ���ҳ���λ�þ���Ԥ�ȱ����ó�USED��100����

 47 unsigned char mem_map [ PAGING_PAGES ] = {0,};

 48

 49 /*

 50  * Free a page of memory at physical address 'addr'. Used by

 51  * 'free_page_tables()'

 52  */

    /*

     * �ͷ�������ַ'addr'����һҳ�ڴ档���ں���'free_page_tables()'��

     */

    //// �ͷ�������ַaddr��ʼ��1ҳ���ڴ档

    // ������ַ1MB���µ��ڴ�ռ������ں˳���ͻ��壬����Ϊ����ҳ����ڴ�ռ䡣���

    // ����addr��Ҫ����1MB��

 53 void free_page(unsigned long addr)

 54 {

    // �����жϲ���������������ַaddr�ĺ����ԡ����������ַaddrС���ڴ�Ͷˣ�1MB����

    // ���ʾ���ں˳������ٻ����У��Դ˲��账�������������ַaddr >= ϵͳ��������

    // �ڴ���߶ˣ�����ʾ������Ϣ�����ں�ֹͣ������

 55         if (addr < LOW_MEM) return;

 56         if (addr >= HIGH_MEMORY)

 57                 panic("trying to free nonexistent page");

    // ����Բ���addr��֤ͨ������ô�͸������������ַ��������ڴ�Ͷ˿�ʼ������ڴ�

    // ҳ��š�ҳ��� = (addr �C LOW_MEM)/4096���ɼ�ҳ��Ŵ�0�ſ�ʼ���𡣴�ʱaddr

    // �д����ҳ��š������ҳ��Ŷ�Ӧ��ҳ��ӳ���ֽڲ�����0�����1���ء���ʱ��ӳ��

    // �ֽ�ֵӦ��Ϊ0����ʾҳ�����ͷš������Ӧҳ���ֽ�ԭ������0����ʾ������ҳ�汾��

    // ���ǿ��еģ�˵���ں˴�������⡣������ʾ������Ϣ��ͣ����

 58         addr -= LOW_MEM;

 59         addr >>= 12;

 60         if (mem_map[addr]--) return;

 61         mem_map[addr]=0;

 62         panic("trying to free free page");

 63 }

 64

 65 /*

 66  * This function frees a continuos block of page tables, as needed

 67  * by 'exit()'. As does copy_page_tables(), this handles only 4Mb blocks.

 68  */

    /*

     * ���溯���ͷ�ҳ���������ڴ�飬'exit()'��Ҫ�ú�������copy_page_tables()

     * ���ƣ��ú���������4Mb���ȵ��ڴ�顣

     */

    //// ����ָ�������Ե�ַ���޳���ҳ�����������ͷŶ�Ӧ�ڴ�ҳ��ָ�����ڴ�鲢�ñ�����С�

    // ҳĿ¼λ��������ַ0��ʼ������1024�ÿ��4�ֽڣ���ռ4K�ֽڡ�ÿ��Ŀ¼��ָ��һ

    // ��ҳ�����ں�ҳ����������ַ0x1000����ʼ��������Ŀ¼�ռ䣩����4��ҳ����ÿ��ҳ����

    // 1024�ÿ��4�ֽڡ����Ҳռ4K��1ҳ���ڴ档�����̣��������ں˴����еĽ���0��1��

    // ��ҳ����ռ�ݵ�ҳ���ڽ��̱�����ʱ���ں�Ϊ�������ڴ�������õ���ÿ��ҳ�����Ӧ1ҳ

    // �����ڴ棬���һ��ҳ������ӳ��4MB�������ڴ档

    // ������from - ��ʼ���Ի���ַ��size - �ͷŵ��ֽڳ��ȡ�

 69 int free_page_tables(unsigned long from,unsigned long size)

 70 {

 71         unsigned long *pg_table;

 72         unsigned long * dir, nr;

 73

    // ���ȼ�����from���������Ի���ַ�Ƿ���4MB�ı߽紦����Ϊ�ú���ֻ�ܴ������������

    // ��from = 0���������˵����ͼ�ͷ��ں˺ͻ�����ռ�ռ䡣

 74         if (from & 0x3fffff)

 75                 panic("free_page_tables called with wrong alignment");

 76         if (!from)

 77                 panic("Trying to free up swapper memory space");

    // Ȼ��������size�����ij�����ռ��ҳĿ¼������4MB�Ľ�λ����������Ҳ����ռҳ������

    // ��Ϊ1��ҳ���ɹ���4MB�����ڴ棬��������������22λ�ķ�ʽ����Ҫ���Ƶ��ڴ泤��ֵ

    // ����4MB�����м���0x3fffff����4Mb -1�����ڵõ���λ���������������������������

    // ���1�����磬���ԭsize = 4.01Mb����ô�ɵõ����size = 2�� ���ż������������

    // ����ַ��Ӧ����ʼĿ¼���Ӧ��Ŀ¼��� = from >> 22����Ϊÿ��ռ4�ֽڣ���������

    // ҳĿ¼����������ַ0��ʼ��ţ����ʵ��Ŀ¼��ָ�� = Ŀ¼���<<2��Ҳ��(from>>20)��

    // ��������0xffcȷ��Ŀ¼��ָ�뷶Χ��Ч��

 78         size = (size + 0x3fffff) >> 22;

 79         dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */

 

    // ��ʱ size ���ͷŵ�ҳ����������ҳĿ¼��������dir����ʼĿ¼��ָ�롣���ڿ�ʼѭ��

    // ����ҳĿ¼������ͷ�ÿ��ҳ���е�ҳ��������ǰĿ¼����Ч��Pλ=0������ʾ��

    // Ŀ¼��û��ʹ�ã���Ӧ��ҳ�������ڣ��������������һ��Ŀ¼������Ŀ¼����ȡ��

    // ҳ����ַ pg_table�����Ը�ҳ���е� 1024 ��������д������ͷ���Чҳ���Pλ=1��

    // ��Ӧ�������ڴ�ҳ�棬���ߴӽ����豸���ͷ���Чҳ���Pλ=0����Ӧ��ҳ�棬���ͷ�

    // �����豸�ж�Ӧ���ڴ�ҳ�棨��Ϊҳ������Ѿ�������ȥ����Ȼ��Ѹ�ҳ�������㣬����

    // ��������һҳ�����һ��ҳ�����б��������Ͼ��ͷŸ�ҳ������ռ�ݵ��ڴ�ҳ�棬

    // ������������һҳĿ¼����ˢ��ҳ�任���ٻ��壬������0��

 80         for ( ; size-->0 ; dir++) {

 81                 if (!(1 & *dir))

 82                         continue;

 83                 pg_table = (unsigned long *) (0xfffff000 & *dir);  // ȡҳ����ַ��

 84                 for (nr=0 ; nr<1024 ; nr++) {

 85                         if (*pg_table) {             // ����ָҳ�������ݲ�Ϊ0����

 86                                 if (1 & *pg_table)   // ��������Ч�����ͷŶ�Ӧҳ��

 87                                         free_page(0xfffff000 & *pg_table);

 88                                 else                 // �����ͷŽ����豸�ж�Ӧҳ��

 89                                         swap_free(*pg_table >> 1);

 90                                 *pg_table = 0;       // ��ҳ�����������㡣

 91                         }

 92                         pg_table++;                  // ָ��ҳ������һ�

 93                 }

 94                 free_page(0xfffff000 & *dir);        // �ͷŸ�ҳ����ռ�ڴ�ҳ�档

 95                 *dir = 0;                            // ��Ӧҳ����Ŀ¼�����㡣

 96         }

 97         invalidate();                                // ˢ��CPUҳ�任���ٻ��塣

 98         return 0;

 99 }

100

101 /*

102  *  Well, here is one of the most complicated functions in mm. It

103  * copies a range of linerar addresses by copying only the pages.

104  * Let's hope this is bug-free, 'cause this one I don't want to debug :-)

105  *

106  * Note! We don't copy just any chunks of memory - addresses have to

107  * be divisible by 4Mb (one page-directory entry), as this makes the

108  * function easier. It's used only by fork anyway.

109  *

110  * NOTE 2!! When from==0 we are copying kernel space for the first

111  * fork(). Then we DONT want to copy a full page-directory entry, as

112  * that would lead to some serious memory waste - we just copy the

113  * first 160 pages - 640kB. Even that is more than we need, but it

114  * doesn't take any more memory - we don't copy-on-write in the low

115  * 1 Mb-range, so the pages can be shared with the kernel. Thus the

116  * special case for nr=xxxx.

117  */

    /*

     * ���ˣ��������ڴ����mm����Ϊ���ӵij���֮һ����ͨ��ֻ�����ڴ�ҳ��

     * ������һ����Χ�����Ե�ַ�е����ݡ� ϣ��������û�д�����Ϊ�Ҳ���

     * �ٵ�����������:-)��

     *

     * ע�⣡���Dz��������κ��ڴ�� - �ڴ��ĵ�ַ��Ҫ��4Mb�ı���������

     * һ��ҳĿ¼���Ӧ���ڴ泤�ȣ�����Ϊ����������ʹ�����ܼ򵥡� ������

     * ����������fork()ʹ�á�

     *

     * ע��2���� ��from==0ʱ��˵������Ϊ��һ��fork()���ø����ں˿ռ䡣

     * ��ʱ���ǾͲ��븴������ҳĿ¼���Ӧ���ڴ棬��Ϊ�������ᵼ���ڴ���

     * ���˷� - ����ֻ�븴�ƿ�ͷ160��ҳ�� - ��Ӧ 640kB����ʹ�Ǹ�����Щ

     * ҳ��Ҳ�Ѿ��������ǵ����󣬵��ⲻ��ռ�ø�����ڴ� - �ڵ� 1Mb �ڴ�

     * ��Χ�����Dz�ִ��дʱ���Ʋ�����������Щҳ��������ں˹����������

     * ��nr=xxxx�����������nr�ڳ�����ָҳ��������

     */

    //// ����ҳĿ¼�����ҳ���

    // ����ָ�����Ե�ַ�ͳ����ڴ��Ӧ��ҳĿ¼���ҳ����Ӷ������Ƶ�ҳĿ¼��ҳ����Ӧ

    // ��ԭ�����ڴ�ҳ����������ҳ��ӳ�������ʹ�á�����ʱ����������ҳ���������ҳ����

    // ԭ�����ڴ��������������˺��������̣������̺����ӽ��̣��������ڴ�����ֱ����һ��

    // ����ִ��д����ʱ���ں˲Ż�Ϊд�������̷����µ��ڴ�ҳ��дʱ���ƻ��ƣ���

    // ����from��to �����Ե�ַ��size����Ҫ���ƣ����������ڴ泤�ȣ���λ���ֽڡ�

118 int copy_page_tables(unsigned long from,unsigned long to,long size)

119 {

120         unsigned long * from_page_table;

121         unsigned long * to_page_table;

122         unsigned long this_page;

123         unsigned long * from_dir, * to_dir;

124         unsigned long new_page;

125         unsigned long nr;

126

    // ���ȼ�����������Դ��ַfrom��Ŀ�ĵ�ַto����Ч�ԡ�Դ��ַ��Ŀ�ĵ�ַ����Ҫ��4Mb

    // �ڴ�߽��ַ�ϡ����������������������Ҫ������Ϊһ��ҳ����1024��ɹ���4Mb�ڴ档

    // Դ��ַ from ��Ŀ�ĵ�ַ to ֻ���������Ҫ����ܱ�֤��һ��ҳ���ĵ�1�ʼ����ҳ��

    // �������ҳ����������������Ч�ġ�  Ȼ��ȡ��Դ��ַ��Ŀ�ĵ�ַ����ʼĿ¼��ָ��

    // ��from_dir��to_dir�����ٸ��ݲ��������ij���size����Ҫ���Ƶ��ڴ��ռ�õ�ҳ����

    // ����Ŀ¼���������μ�ǰ���78��79�еĽ��͡�

127         if ((from&0x3fffff) || (to&0x3fffff))

128                 panic("copy_page_tables called with wrong alignment");

129         from_dir = (unsigned long *) ((from>>20) & 0xffc); /* _pg_dir = 0 */

130         to_dir = (unsigned long *) ((to>>20) & 0xffc);

131         size = ((unsigned) (size+0x3fffff)) >> 22;

    // �ڵõ���Դ��ʼĿ¼��ָ��from_dir��Ŀ����ʼĿ¼��ָ��to_dir�Լ���Ҫ���Ƶ�ҳ��

    // ���� size �����濪ʼ��ÿ��ҳĿ¼����������1ҳ�ڴ��������Ӧ��ҳ�������ҿ�ʼ

    // ҳ����Ʋ��������Ŀ��Ŀ¼��ָ����ҳ���Ѿ����ڣ�P=1��������������� ���ԴĿ

    // ¼����Ч����ָ����ҳ�������ڣ�P=0���������ѭ��������һ��ҳĿ¼�

132         for( ; size-->0 ; from_dir++,to_dir++) {

133                 if (1 & *to_dir)

134                         panic("copy_page_tables: already exist");

135                 if (!(1 & *from_dir))

136                         continue;

 

    // ����֤�˵�ǰԴĿ¼���Ŀ��������֮������ȡԴĿ¼����ҳ����ַfrom_page_table��

    // Ϊ�˱���Ŀ��Ŀ¼���Ӧ��ҳ������Ҫ�����ڴ���������1ҳ�����ڴ�ҳ�����ȡ����ҳ��

    // ����get_free_page() ����0����˵��û�����뵽�����ڴ�ҳ�棬�������ڴ治�������Ƿ�

    // ��-1ֵ�˳���

137                 from_page_table = (unsigned long *) (0xfffff000 & *from_dir);

138                 if (!(to_page_table = (unsigned long *) get_free_page()))

139                         return -1;      /* Out of memory, see freeing */

 

    // ������������Ŀ��Ŀ¼����Ϣ�������3λ��λ������ǰĿ��Ŀ¼�����7����ʾ��Ӧ

    // ҳ��ӳ����ڴ�ҳ�����û����ģ����ҿɶ�д�����ڣ�Usr, R/W, Present���� �����U/S

    // λ��0����R/W��û�����á���� U/S��1���� R/W��0����ô�������û���Ĵ����ֻ��

    // ��ҳ�档���U/S��R/W����λ������ж�д��Ȩ�ޣ���Ȼ����Ե�ǰ������ҳĿ¼���Ӧ

    // ��ҳ����������Ҫ���Ƶ�ҳ����������������ں˿ռ䣬����踴��ͷ160ҳ��Ӧ��ҳ����

    // ��nr= 160������Ӧ�ڿ�ʼ640KB�����ڴ档������Ҫ����һ��ҳ���е�����1024��ҳ����

    // ��nr= 1024������ӳ��4MB�����ڴ档

140                 *to_dir = ((unsigned long) to_page_table) | 7;

141                 nr = (from==0)?0xA0:1024;

 

    // ��ʱ���ڵ�ǰҳ������ʼѭ������ָ����nr���ڴ�ҳ������ȡ��Դҳ�������ݣ����

    // ��ǰԴҳ��û��ʹ�ã�������Ϊ0�������ø��Ƹñ������������һ�

142                 for ( ; nr-- > 0 ; from_page_table++,to_page_table++) {

143                         this_page = *from_page_table;

144                         if (!this_page)

145                                 continue;

    // ����ñ��������ݣ����������λP=0����ñ����Ӧ��ҳ������ڽ����豸�С���������

    // ��1ҳ�ڴ棬���ӽ����豸�ж����ҳ�棨�������豸���еĻ�����Ȼ�󽫸�ҳ����Ƶ�

    // Ŀ��ҳ�����С����޸�Դҳ��������ָ�����������ڴ�ҳ�������ñ����־Ϊ��ҳ���ࡱ

    // ����7��Ȼ�����������һҳ�������λҳ������ R/W ��־��λ1��0��������ҳ����

    // ��Ӧ���ڴ�ҳ��ֻ����Ȼ�󽫸�ҳ����Ƶ�Ŀ��ҳ���С�

146                         if (!(1 & this_page)) {

147                                 if (!(new_page = get_free_page()))

148                                         return -1;

149                                 read_swap_page(this_page>>1, (char *) new_page);

150                                 *to_page_table = this_page;

151                                 *from_page_table = new_page | (PAGE_DIRTY | 7);

152                                 continue;

153                         }

154                         this_page &= ~2;

155                         *to_page_table = this_page;

 

    // �����ҳ������ָ����ҳ��ĵ�ַ��1MB���ϣ�����Ҫ�����ڴ�ҳ��ӳ������mem_map[]��

    // ���Ǽ���ҳ��ţ�������Ϊ������ҳ��ӳ��������Ӧ�����������ô�����������λ��1MB

    // ���µ�ҳ�棬˵�����ں�ҳ�棬��˲���Ҫ��mem_map[]�������á���Ϊ mem_map[]����

    // �ڹ������ڴ����е�ҳ��ʹ������� ��˶����ں��ƶ�������0�в��ҵ���fork()����

    // ����1ʱ����������init()�������ڴ�ʱ���Ƶ�ҳ�滹��Ȼ�����ں˴��������������

    // �ж��е���䲻��ִ�У�����0 ��ҳ����Ȼ������ʱ��д��ֻ�е����� fork() �ĸ�����

    // ���봦�����ڴ�����ҳ��λ�ô���1MB��ʱ�Ż�ִ�С����������Ҫ�ڽ��̵���execve()��

    // ��װ��ִ�����³������ʱ�Ż���֡�

    // 157����京������Դҳ������ָ�ڴ�ҳҲΪֻ������Ϊ���ڿ�ʼ�����������̹����ڴ�

    // ���ˡ�������1��������Ҫ����д�����������ͨ��ҳ�쳣д��������Ϊִ��д�����Ľ�

    // �̷���1ҳ�¿���ҳ�棬Ҳ������дʱ���ƣ�copy on write��������

156                         if (this_page > LOW_MEM) {

157                                 *from_page_table = this_page; // ��Դҳ����Ҳֻ����

158                                 this_page -= LOW_MEM;

159                                 this_page >>= 12;

160                                 mem_map[this_page]++;

161                         }

162                 }

163         }

164         invalidate();                            // ˢ��ҳ�任���ٻ��塣

165         return 0;

166 }

167

168 /*

169  * This function puts a page in memory at the wanted address.

170  * It returns the physical address of the page gotten, 0 if

171  * out of memory (either when trying to access page-table or

172  * page.)

173  */

    /*

     * ���溯����һ�ڴ�ҳ����ã�ӳ�䣩��ָ�����Ե�ַ����������ҳ��

     * ��������ַ������ڴ治��(�ڷ���ҳ����ҳ��ʱ)���򷵻�0��

     */

    // ��һ�����ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������

    // ����˵�ǰ����Ե�ַ�ռ���ָ����ַaddress����ҳ��ӳ�䵽���ڴ���ҳ��page�ϡ���Ҫ

    // �����������ҳĿ¼���ҳ����������ָ��ҳ�����Ϣ�����ɹ��򷵻�����ҳ���ַ�� ��

    // ����ȱҳ�쳣��C����do_no_page() �л���ô˺���������ȱҳ������쳣�������κ�ȱ

    // ҳԵ�ʶ���ҳ�����޸�ʱ��������Ҫˢ��CPU��ҳ�任���壨���Translation Lookaside

    // Buffer - TLB������ʹҳ�����б�־P����0�޸ij�1����Ϊ��Чҳ��ᱻ���壬��˵�

    // �޸���һ����Ч��ҳ����ʱ����Ҫˢ�¡��ڴ˾ͱ���Ϊ���õ���Invalidate()������

    // ����page�Ƿ�������ڴ�����ijһҳ�棨ҳ֡��ҳ�򣩵�ָ�룻address�����Ե�ַ��

174 static unsigned long put_page(unsigned long page,unsigned long address)

175 {

176         unsigned long tmp, *page_table;

177

178 /* NOTE !!! This uses the fact that _pg_dir=0 */

    /* ע��!!! ����ʹ����ҳĿ¼������ַ_pg_dir=0������ */

179

    // �����жϲ������������ڴ�ҳ��page ����Ч�ԡ������ҳ��λ�õ���LOW_MEM��1MB����

    // ����ϵͳʵ�ʺ����ڴ�߶� HIGH_MEMORY���򷢳����档LOW_MEM �����ڴ��������е���

    // С��ʼλ�á���ϵͳ�����ڴ�С�ڻ����6MBʱ�����ڴ�����ʼ��LOW_MEM�����ٲ鿴һ

    // �¸� pageҳ���Ƿ����Ѿ������ҳ�棬���ж������ڴ�ҳ��ӳ���ֽ�ͼ mem_map[]����

    // Ӧ�ֽ��Ƿ��Ѿ���λ����û�����跢�����档

180         if (page < LOW_MEM || page >= HIGH_MEMORY)

181                 printk("Trying to put page %p at %p\n",page,address);

182         if (mem_map[(page-LOW_MEM)>>12] != 1)

183                 printk("mem_map disagrees with %p at %p\n",page,address);

 

    // Ȼ����ݲ���ָ�������Ե�ַaddress��������ҳĿ¼���ж�Ӧ��Ŀ¼��ָ�룬������ȡ��

    // ����ҳ����ַ�� �����Ŀ¼����Ч��P=1������ָ����ҳ�����ڴ��У������ȡ��ָ��ҳ��

    // ��ַ�ŵ�page_table �����С���������һ����ҳ���ҳ��ʹ�ã����ڶ�ӦĿ¼��������Ӧ

    // ��־��7 �C User��U/S��R/W����Ȼ�󽫸�ҳ����ַ�ŵ�page_table�����С�

184         page_table = (unsigned long *) ((address>>20) & 0xffc);

185         if ((*page_table)&1)

186                 page_table = (unsigned long *) (0xfffff000 & *page_table);

187         else {

188                 if (!(tmp=get_free_page()))

189                         return 0;

190                 *page_table = tmp | 7;

191                 page_table = (unsigned long *) tmp;

192         }

    // ������ҵ���ҳ�� page_table ���������ҳ�������ݣ���������ҳ��page�ĵ�ַ�����

    // ��ͬʱ��λ3����־��U/S��W/R��P������ҳ������ҳ���е�����ֵ�������Ե�ַλ21 --

    // λ12��ɵ�10���ص�ֵ��ÿ��ҳ��������1024�0 -- 0x3ff����

193         page_table[(address>>12) & 0x3ff] = page | 7;

194 /* no need for invalidate */

    /* ����Ҫˢ��ҳ�任���ٻ��� */

195         return page;                    // ��������ҳ���ַ��

196 }

197

198 /*

199  * The previous function doesn't work very well if you also want to mark

200  * the page dirty: exec.c wants this, as it has earlier changed the page,

201  * and we want the dirty-status to be correct (for VM). Thus the same

202  * routine, but this time we mark it dirty too.

203  */

    /*

     * �����Ҳ������ҳ�����޸ı�־������һ�����������ò��Ǻܺã�exec.c����

     * ��Ҫ�������á���Ϊexec.c�к������ڷ���ҳ��֮ǰ�޸Ĺ�ҳ�����ݡ�Ϊ��ʵ

     * ��VM��������Ҫ����ȷ�������޸�״̬��־����������������������ͬ�ĺ�

     * �������Ǹú����ڷ���ҳ��ʱ���ҳ���־Ϊ���޸�״̬��

     */

    // ��һ�������޸Ĺ��������ڴ�ҳ��ӳ�䵽���Ե�ַ�ռ�ָ������

    // �ú�������һ������put_page()������ȫһ�������˱�������223������ҳ��������ʱ��

    // ͬʱ��������ҳ�����޸ı�־��λ6��PAGE_DIRTY����

204 unsigned long put_dirty_page(unsigned long page, unsigned long address)

205 {

206         unsigned long tmp, *page_table;

207

208 /* NOTE !!! This uses the fact that _pg_dir=0 */

209

210         if (page < LOW_MEM || page >= HIGH_MEMORY)

211                 printk("Trying to put page %p at %p\n",page,address);

212         if (mem_map[(page-LOW_MEM)>>12] != 1)

213                 printk("mem_map disagrees with %p at %p\n",page,address);

214         page_table = (unsigned long *) ((address>>20) & 0xffc);

215         if ((*page_table)&1)

216                 page_table = (unsigned long *) (0xfffff000 & *page_table);

217         else {

218                 if (!(tmp=get_free_page()))

219                         return 0;

220                 *page_table = tmp|7;

221                 page_table = (unsigned long *) tmp;

222         }

223         page_table[(address>>12) & 0x3ff] = page | (PAGE_DIRTY | 7);

224 /* no need for invalidate */

225         return page;

226 }

227

    //// ȡ��д����ҳ�溯��������ҳ�쳣�жϹ�����д�����쳣�Ĵ�����дʱ���ƣ���

    // ���ں˴�������ʱ���½����븸���̱����óɹ�������������ڴ�ҳ�棬����������Щҳ��

    // �������ó�ֻ��ҳ�档�����½��̻�ԭ������Ҫ���ڴ�ҳ��д����ʱ��CPU �ͻ��⵽���

    // ���������ҳ��д�����쳣������������������ں˾ͻ������ж�Ҫд��ҳ���Ƿ񱻹�����

    // ��û�����ҳ�����óɿ�дȻ���˳�����ҳ���dz��ڹ���״̬������Ҫ��������һ��ҳ�沢

    // ���Ʊ�дҳ�����ݣ��Թ�д���̵���ʹ�á�������ȡ����

    // �������Ϊҳ����ָ�룬��������ַ��[ un_wp_page -- Un-Write Protect Page]

228 void un_wp_page(unsigned long * table_entry)

229 {

230         unsigned long old_page,new_page;

231

    // ����ȡ����ָ����ҳ����������ҳ��λ�ã���ַ�����жϸ�ҳ���Ƿ��ǹ���ҳ�档���ԭ

    // ҳ���ַ�����ڴ�Ͷ� LOW_MEM����ʾ�����ڴ����У�����������ҳ��ӳ���ֽ�ͼ������

    // ֵΪ1����ʾҳ���������1�Σ�ҳ��û�б������������ڸ�ҳ���ҳ�������� R/W ��־

    // ����д������ˢ��ҳ�任���ٻ��壬Ȼ�󷵻ء���������ڴ�ҳ���ʱֻ��һ������ʹ�ã�

    // ���Ҳ����ں��еĽ��̣���ֱ�Ӱ����Ը�Ϊ��д���ɣ���������������һ����ҳ�档

232         old_page = 0xfffff000 & *table_entry;      // ȡָ��ҳ����������ҳ���ַ��

233         if (old_page >= LOW_MEM && mem_map[MAP_NR(old_page)]==1) {

234                 *table_entry |= 2;

235                 invalidate();

236                 return;

237         }

    // �������Ҫ�����ڴ���������һҳ����ҳ���ִ��д�����Ľ��̵���ʹ�ã�ȡ��ҳ�湲����

    // ���ԭҳ������ڴ�Ͷˣ�����ζ�� mem_map[] > 1��ҳ���ǹ����ģ�����ԭҳ���ҳ

    // ��ӳ���ֽ�����ֵ�ݼ�1��Ȼ��ָ��ҳ�������ݸ���Ϊ��ҳ���ַ�����ÿɶ�д�ȱ�־

    // ��U/S��R/W��P������ˢ��ҳ�任���ٻ���֮�����ԭҳ�����ݸ��Ƶ���ҳ�档

238         if (!(new_page=get_free_page()))

239                 oom();                             // Out of Memory���ڴ治��������

240         if (old_page >= LOW_MEM)

241                 mem_map[MAP_NR(old_page)]--;

242         copy_page(old_page,new_page);

243         *table_entry = new_page | 7;

244         invalidate();

245 }      

246

247 /*

248  * This routine handles present pages, when users try to write

249  * to a shared page. It is done by copying the page to a new address

250  * and decrementing the shared-page counter for the old page.

251  *

252  * If it's in code space we exit with a segment error.

253  */

    /*

     * ���û���ͼ��һ����ҳ����дʱ���ú��������Ѵ��ڵ��ڴ�ҳ�棨дʱ���ƣ���

     * ����ͨ����ҳ�渴�Ƶ�һ���µ�ַ�ϲ��ҵݼ�ԭҳ��Ĺ�������ֵʵ�ֵġ�

     *

     * ������ڴ���ռ䣬���Ǿ���ʾ�γ�����Ϣ���˳���

     */

    //// ִ��д����ҳ�洦����

    // ��д����ҳ�洦����������ҳ�쳣�жϴ��������е��õ�C��������page.s�����б����á�

    // ��������error_code �� address �ǽ�����дд����ҳ��ʱ�� CPU�����쳣���Զ����ɵġ�

    // error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���

    // �쳣��ҳ�����Ե�ַ��д����ҳ��ʱ�踴��ҳ�棨дʱ���ƣ���

254 void do_wp_page(unsigned long error_code,unsigned long address)

255 {

    // �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address

    // С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����

    // �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ

    // ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������

    // �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���

256         if (address < TASK_SIZE)

257                 printk("\n\rBAD! KERNEL MEMORY WP-ERR!\n\r");

258         if (address - current->start_code > TASK_SIZE) {

259                 printk("Bad things happen: page error in do_wp_page\n\r");

260                 do_exit(SIGSEGV);

261         }

262 #if 0

263 /* we cannot do this yet: the estdio library writes to code space */

264 /* stupid, stupid. I really want the libc.a from GNU */

    /* �������ڻ���������������Ϊestdio����ڴ���ռ�ִ��д���� */

    /* ����̫�޴��ˡ��������GNU�õ�libc.a�⡣*/

    // ������Ե�ַλ�ڽ��̵Ĵ���ռ��У�����ִֹ�г�����Ϊ������ֻ���ġ�

265         if (CODE_SPACE(address))

266                 do_exit(SIGSEGV);

267 #endif

    // �������溯��un_wp_page()������ȡ��ҳ�汣������������ҪΪ��׼���ò�����������

    // ���Ե�ַaddressָ��ҳ����ҳ���е�ҳ����ָ�룬����㷽���ǣ�

    // �� ((address>>10) & 0xffc)������ָ�����Ե�ַ��ҳ������ҳ���е�ƫ�Ƶ�ַ����Ϊ

    // �������Ե�ַ�ṹ��(address>>12) ����ҳ�����е���������ÿ��ռ4���ֽڣ���˳�

    // 4��(address>>12)<<2 = (address>>10)&0xffc �Ϳɵõ�ҳ�����ڱ��е�ƫ�Ƶ�ַ��

    // �����&0xffc�������Ƶ�ַ��Χ��һ��ҳ���ڡ� ����Ϊֻ�ƶ���10λ��������2λ

    // �����Ե�ַ��12 λ�е����2λ��ҲӦ���ε��� ��������Ե�ַ��ҳ������ҳ����ƫ

    // �Ƶ�ֱַ��һЩ�ı�ʾ������(((address>>12) & 0x3ff)<<2 )��

    // �� (0xfffff000 & *((address>>20) &0xffc))������ȡĿ¼����ҳ���ĵ�ֵַ�����У�

    // ((address>>20) &0xffc)����ȡ���Ե�ַ�е�Ŀ¼��������Ŀ¼���е�ƫ��λ�á���Ϊ

    // address>>22 ��Ŀ¼������ֵ����ÿ��4���ֽڣ���˳���4�� (address>>22)<<2

    // = (address>>20) ����ָ������Ŀ¼���е�ƫ�Ƶ�ַ�� &0xffc��������Ŀ¼������ֵ

    // �����2λ����Ϊֻ�ƶ���20λ��������2λ��ҳ�����������ݣ�Ӧ�����ε�����

    // *((address>>20) &0xffc) ����ȡָ��Ŀ¼���������ж�Ӧҳ����������ַ���������

    // 0xffffff000�������ε�ҳĿ¼�������е�һЩ��־λ��Ŀ¼���12λ����ֱ�۱�ʾΪ

    // (0xffffff000 & *((unsigned long *) (((address>>22) & 0x3ff)<<2)))��

    // �� �ɢ���ҳ������ҳ����ƫ�Ƶ�ַ���� ����Ŀ¼���������ж�Ӧҳ����������ַ����

    // �õ�ҳ�����ָ�루������ַ��������Թ�����ҳ����и��ơ�

268         un_wp_page((unsigned long *)

269                 (((address>>10) & 0xffc) + (0xfffff000 &

270                 *((unsigned long *) ((address>>20) &0xffc)))));

271

272 }

273

    //// дҳ����֤��

    // ��ҳ�治��д������ҳ�档��fork.c�е�34�б��ڴ���֤ͨ�ú���verify_area()���á�

    // ����address��ָ��ҳ����4G�ռ��е����Ե�ַ��

274 void write_verify(unsigned long address)

275 {

276         unsigned long page;

277

    // ����ȡָ�����Ե�ַ��Ӧ��ҳĿ¼�����Ŀ¼���еĴ���λ��P���ж�Ŀ¼���Ӧ��ҳ��

    // �Ƿ���ڣ�����λP=1?�����������ڣ�P=0���򷵻ء�������������Ϊ���ڲ����ڵ�ҳ��û

    // �й�����дʱ���ƿ��ԣ�����������Դ˲����ڵ�ҳ��ִ��д����ʱ��ϵͳ�ͻ���Ϊȱҳ��

    // ����ȥִ��do_no_page()����Ϊ����ط�ʹ�� put_page()����ӳ��һ������ҳ�档

    // ���ų����Ŀ¼����ȡҳ����ַ������ָ��ҳ����ҳ���е�ҳ����ƫ��ֵ���ö�Ӧ��ַ��ҳ

    // ����ָ�롣�ڸñ����а����Ÿ������Ե�ַ��Ӧ������ҳ�档

278         if (!( (page = *((unsigned long *) ((address>>20) & 0xffc)) )&1))

279                 return;

280         page &= 0xfffff000;

281         page += ((address>>10) & 0xffc);

    // Ȼ���жϸ�ҳ�����е�λ1��R/W����λ0��P����־�������ҳ�治��д��R/W=0���Ҵ��ڣ�

    // ��ô��ִ�й�������͸���ҳ�������дʱ���ƣ�������ʲôҲ������ֱ���˳���

282         if ((3 & *(unsigned long *) page) == 1)  /* non-writeable, present */

283                 un_wp_page((unsigned long *) page);

284         return;

285 }

286

    //// ȡ��һҳ�����ڴ�ҳ��ӳ�䵽ָ�����Ե�ַ����

    // get_free_page()��������ȡ�������ڴ�����һҳ�����ڴ档���������򲻽��ǻ�ȡ��һҳ

    // �����ڴ�ҳ�棬����һ������put_page()��������ҳ��ӳ�䵽ָ�������Ե�ַ����

    // ����address��ָ��ҳ������Ե�ַ��

287 void get_empty_page(unsigned long address)

288 {

289         unsigned long tmp;

290

    // ������ȡ��һ����ҳ�棬���߲��ܽ���ȡҳ����õ�ָ����ַ��������ʾ�ڴ治������Ϣ��

    // 292����Ӣ��ע�͵ĺ����ǣ�free_page()�����IJ���tmp��0Ҳû�й�ϵ���ú��������

    // �������������ء�

291         if (!(tmp=get_free_page()) || !put_page(tmp,address)) {

292                 free_page(tmp);         /* 0 is ok - ignored */

293                 oom();

294         }

295 }

296

297 /*

298  * try_to_share() checks the page at address "address" in the task "p",

299  * to see if it exists, and if it is clean. If so, share it with the current

300  * task.

301  *

302  * NOTE! This assumes we have checked that p != current, and that they

303  * share the same executable or library.

304  */

    /*

     * try_to_share()������"p"�м��λ�ڵ�ַ"address"����ҳ�棬��ҳ���Ƿ���ڣ�

     * �Ƿ�ɾ�������Ǹɾ��Ļ������뵱ǰ��������

     *

     * ע�⣡���������Ѽٶ�p !=��ǰ���񣬲������ǹ���ͬһ��ִ�г��������

     */

    //// ���ԶԵ�ǰ����ָ����ַ����ҳ����й���������

    // ��ǰ���������p��ͬһִ�д��룬Ҳ������Ϊ��ǰ��������p����ִ��fork����������

    // ���̣�������ǵĴ�������һ�������δ�����ݶ����������޸���ô���ݶ�����ҲӦһ����

    // ���� address �ǽ����е��߼���ַ�����ǵ�ǰ�������� p ���̹���ҳ����߼�ҳ���ַ��

    // ����p�ǽ�������ҳ��Ľ��̡����p����address����ҳ����ڲ���û�б��޸Ĺ��Ļ���

    // ���õ�ǰ������p���̹���֮��ͬʱ����Ҫ��ָ֤���ĵ�ַ���Ƿ��Ѿ�������ҳ�棬����

    // ����������������أ�1 - ҳ�湲�������ɹ���0 - ʧ�ܡ�

305 static int try_to_share(unsigned long address, struct task_struct * p)

306 {

307         unsigned long from;

308         unsigned long to;

309         unsigned long from_page;

310         unsigned long to_page;

311         unsigned long phys_addr;

312

    // ���ȷֱ����ָ������p�к͵�ǰ�������߼���ַaddress��Ӧ��ҳĿ¼�Ϊ�˼��㷽��

    // �����ָ���߼���ַaddress����'�߼�'ҳĿ¼��ţ����Խ��̿ռ䣨0 - 64MB�������ҳ

    // Ŀ¼��š���'�߼�'ҳĿ¼��ż��Ͻ���p ��CPU 4G���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼�

    // ���õ�����p�е�ַ address ��ҳ������Ӧ��4G ���Կռ��е�ʵ��ҳĿ¼��from_page��

    // ��'�߼�'ҳĿ¼��ż��ϵ�ǰ����CPU 4G ���Կռ�����ʼ��ַ��Ӧ��ҳĿ¼��������

    // �õ���ǰ�����е�ַaddress��ҳ������Ӧ��4G���Կռ��е�ʵ��ҳĿ¼��to_page��

313         from_page = to_page = ((address>>20) & 0xffc);

314         from_page += ((p->start_code>>20) & 0xffc);      // p����Ŀ¼�

315         to_page += ((current->start_code>>20) & 0xffc);  // ��ǰ����Ŀ¼�

 

    // �ڵõ�p���̺͵�ǰ����address��Ӧ��Ŀ¼�������ֱ�Խ���p�͵�ǰ���̽��д�����

    // �������ȶ�p���̵ı�����в�����Ŀ����ȡ��p������ address��Ӧ�������ڴ�ҳ���ַ��

    // ���Ҹ�����ҳ����ڣ����Ҹɾ���û�б��޸Ĺ������ࣩ��

    // ��������ȡĿ¼�����ݡ������Ŀ¼����Ч��P=0������ʾĿ¼���Ӧ�Ķ���ҳ�������ڣ�

    // ���Ƿ��ء�����ȡ��Ŀ¼���Ӧҳ����ַfrom���Ӷ�������߼���ַaddress��Ӧ��ҳ����

    // ָ�룬��ȡ����ҳ����������ʱ������phys_addr�С�

316 /* is there a page-directory at from? */

    /* ��from���Ƿ����ҳĿ¼�*/

317         from = *(unsigned long *) from_page;           // p����Ŀ¼�����ݡ�

318         if (!(from & 1))

319                 return 0;

320         from &= 0xfffff000;                            // ҳ����ַ��

321         from_page = from + ((address>>10) & 0xffc);    // ҳ����ָ�롣

322         phys_addr = *(unsigned long *) from_page;      // ҳ�������ݡ�

    // ���ſ���ҳ����ӳ�������ҳ���Ƿ���ڲ��Ҹɾ��� 0x41 ��Ӧҳ�����е�D��Dirty����

    // P��Present����־�����ҳ�治�ɾ�����Ч�򷵻ء�Ȼ�����ǴӸñ�����ȡ������ҳ���ַ

    // �ٱ�����phys_addr�С���������ټ��һ���������ҳ���ַ����Ч�ԣ�������Ӧ�ó���

    // �������������ֵַ��Ҳ��Ӧ��С���ڴ�Ͷ�(1MB)��

323 /* is the page clean and present? */

    /* ����ҳ��ɾ����Ҵ�����*/

324         if ((phys_addr & 0x41) != 0x01)

325                 return 0;

326         phys_addr &= 0xfffff000;                       // ����ҳ���ַ��

327         if (phys_addr >= HIGH_MEMORY || phys_addr < LOW_MEM)

328                 return 0;

 

    // �������ȶԵ�ǰ���̵ı�����в�����Ŀ����ȡ�õ�ǰ������address��Ӧ��ҳ�����ַ��

    // ���Ҹ�ҳ���û��ӳ������ҳ�棬����P=0��

    // ����ȡ��ǰ����ҳĿ¼��������to�������Ŀ¼����Ч��P=0������Ŀ¼���Ӧ�Ķ���ҳ��

    // �����ڣ�������һ����ҳ�������ҳ����������Ŀ¼��to_page���ݣ�����ָ����ڴ�ҳ�档

329         to = *(unsigned long *) to_page;               // ��ǰ����Ŀ¼�����ݡ�

330         if (!(to & 1))

331                 if (to = get_free_page())

332                         *(unsigned long *) to_page = to | 7;

333                 else

334                         oom();

    // ����ȡĿ¼���е�ҳ����ַ��to������ҳ��������ֵ<<2����ҳ�����ڱ���ƫ�Ƶ�ַ���õ�

    // ҳ�����ַ��to_page����Ը�ҳ��������ʱ���Ǽ������Ӧ������ҳ���Ѿ����ڣ�

    // ��ҳ����Ĵ���λP=1����˵��ԭ�������빲������p�ж�Ӧ������ҳ�棬�����������Լ�

    // �Ѿ�ռ���ˣ�ӳ���У�����ҳ�档����˵���ں˳�����������

335         to &= 0xfffff000;                              // ҳ����ַ��

336         to_page = to + ((address>>10) & 0xffc);        // ҳ�����ַ��

337         if (1 & *(unsigned long *) to_page)

338                 panic("try_to_share: to_page already exists");

 

    // ���ҵ��˽���p���߼���ַaddress����Ӧ�ĸɾ����Ҵ��ڵ�����ҳ�棬����Ҳȷ���˵�ǰ

    // �������߼���ַ address ����Ӧ�Ķ���ҳ�����ַ֮���������ڶ����ǽ��й���������

    // �����ܼ򵥣��������ȶ�p���̵�ҳ��������޸ģ�������д������R/W=0��ֻ������־��

    // Ȼ���õ�ǰ���̸��� p���̵����ҳ�����ʱ��ǰ�����߼���ַ address ��ҳ�漴��

    // ӳ�䵽p�����߼���ַaddress��ҳ��ӳ�������ҳ���ϡ�

339 /* share them: write-protect */

    /* �����ǽ��й���������д���� */

340         *(unsigned long *) from_page &= ~2;

341         *(unsigned long *) to_page = *(unsigned long *) from_page;

    // ���ˢ��ҳ�任���ٻ��塣��������������ҳ���ҳ��ţ�������Ӧҳ��ӳ���ֽ���������

    // �����õ���1����󷵻�1����ʾ���������ɹ���

342         invalidate();

343         phys_addr -= LOW_MEM;

344         phys_addr >>= 12;                              // ��ҳ��š�

345         mem_map[phys_addr]++;

346         return 1;

347 }

348

349 /*

350  * share_page() tries to find a process that could share a page with

351  * the current one. Address is the address of the wanted page relative

352  * to the current data space.

353  *

354  * We first check if it is at all feasible by checking executable->i_count.

355  * It should be >1 if there are other tasks sharing this inode.

356  */

    /*

     * share_page()��ͼ�ҵ�һ�����̣��������뵱ǰ���̹���ҳ�档����address��

     * ��ǰ�������ݿռ�������������ijҳ���ַ��

     *

     * ��������ͨ�����executable->i_count����֤�Ƿ���С���������������ѹ���

     * ��inode������Ӧ�ô���1��

     */

    //// ����ҳ�洦����

    // �ڷ���ȱҳ�쳣ʱ�����ȿ����ܷ�������ͬһ��ִ���ļ����������̽���ҳ�湲��������

    // �ú��������ж�ϵͳ���Ƿ�����һ������Ҳ�����е�ǰ����һ����ִ���ļ������У�����

    // ϵͳ��ǰ����������Ѱ���������������ҵ�������������ͳ������乲��ָ����ַ����

    // ҳ�档��ϵͳ��û�������������������뵱ǰ������ͬ��ִ���ļ�����ô����ҳ�������

    // ǰ�����������ڣ���˺��������˳����ж�ϵͳ���Ƿ�����һ������Ҳ��ִ��ͬһ��ִ��

    // �ļ��ķ��������ý����������ݽṹ�е� executable �ֶΣ���library�ֶΣ������ֶ�

    // ָ���������ִ�г��򣨻�ʹ�õĿ��ļ������ڴ��е� i�ڵ㡣���ݸ� i�ڵ�����ô���

    // i_count ���ǿ��Խ��������жϡ� ���ڵ��i_countֵ����1�������ϵͳ������������

    // ��������ͬһ��ִ���ļ�������ļ��������ǿ����ٶ�����ṹ��������������Ƚ��Ƿ�

    // ����ͬ�� executable�ֶΣ��� library�ֶΣ������ȷ�����������������ִͬ���ļ�

    // �������

    // ����inode�������й���ҳ�����ִ���ļ����ڴ�i�ڵ㡣address�ǽ����е��߼���ַ��

    // ���ǵ�ǰ��������p���̹���ҳ����߼�ҳ���ַ������1 �C���������ɹ���0 - ʧ�ܡ�

357 static int share_page(struct m_inode * inode, unsigned long address)

358 {

359         struct task_struct ** p;

360

    // ���ȼ��һ�²���ָ�����ڴ� i�ڵ����ü���ֵ��������ڴ� i�ڵ�����ü���ֵ����

    // 1��executable->i_count =1������i�ڵ�ָ��գ���ʾ��ǰϵͳ��ֻ��1������������

    // ��ִ���ļ������ṩ��i�ڵ���Ч������޹������ԣ�ֱ���˳�������

361         if (inode->i_count < 2 || !inode)

362                 return 0;

    // ��������������������������Ѱ���뵱ǰ���̿ɹ���ҳ��Ľ��̣���������ִͬ���ļ�

    // ����һ�����̣������Զ�ָ����ַ��ҳ����й������������߼���ַaddressС�ڽ��̿�

    // �ļ����߼���ַ�ռ����ʼ��ַLIBRARY_OFFSET�������������ҳ���ڽ���ִ���ļ���Ӧ

    // ���߼���ַ�ռ䷶Χ�ڣ����Ǽ��һ��ָ��i�ڵ��Ƿ�����̵�ִ���ļ�i�ڵ㣨������

    // ��executable��ͬ��������ͬ�����Ѱ�ҡ��������߼���ַaddress���ڵ��ڽ��̿��ļ�

    // ���߼���ַ�ռ����ʼ��ַLIBRARY_OFFSET���������Ҫ������ҳ���ڽ���ʹ�õĿ��ļ�

    // �У����Ǽ��ָ���ڵ� inode �Ƿ�����̵Ŀ��ļ� i�ڵ���ͬ��������ͬ�����Ѱ�ҡ�

    // ����ҵ�ij������p����executable��library��ָ���Ľڵ�inode��ͬ�������ҳ��

    // ��̽����try_to_share() ����ҳ�湲���������������ɹ�����������1�����򷵻�0��

    // ��ʾ����ҳ�����ʧ�ܡ�

363         for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {

364                 if (!*p)                         // �������������У������Ѱ�ҡ�

365                         continue;

366                 if (current == *p)               // ������ǵ�ǰ����Ҳ����Ѱ�ҡ�

367                         continue;

368                 if (address < LIBRARY_OFFSET) {

369                         if (inode != (*p)->executable)   // ����ִ���ļ�i�ڵ㡣

370                                 continue;

371                 } else {

372                         if (inode != (*p)->library)      // ����ʹ�ÿ��ļ�i�ڵ㡣

373                                 continue;

374                 }

375                 if (try_to_share(address,*p))    // ���Թ���ҳ�档

376                         return 1;

377         }

378         return 0;

379 }

380

    //// ִ��ȱҳ������

    // ���ʲ�����ҳ��Ĵ���������ҳ�쳣�жϴ��������е��ô˺�������page.s�����б����á�

    // ��������error_code �� address �ǽ����ڷ���ҳ��ʱ�� CPU��ȱҳ�����쳣���Զ����ɡ�

    // error_codeָ���������ͣ��μ����¿�ʼ���ġ��ڴ�ҳ������쳣��һ�ڣ�address�Dz���

    // �쳣��ҳ�����Ե�ַ��

    // �ú������Ȳ鿴��ȱҳ�Ƿ��ڽ����豸�У������򽻻����������������Ѽ��ص���ͬ�ļ�

    // ����ҳ�湲��������ֻ�����ڽ��̶�̬�����ڴ�ҳ���ֻ��ӳ��һҳ�����ڴ�ҳ���ɡ�����

    // ���������ɹ�����ôֻ�ܴ���Ӧ�ļ��ж�����ȱ������ҳ�浽ָ�����Ե�ַ����

381 void do_no_page(unsigned long error_code,unsigned long address)

382 {

383         int nr[4];

384         unsigned long tmp;

385         unsigned long page;

386         int block,i;

387         struct m_inode * inode;

388

    // �����ж�CPU���ƼĴ���CR2����������ҳ���쳣�����Ե�ַ��ʲô��Χ�С����address

    // С�� TASK_SIZE��0x4000000����64MB������ʾ�쳣ҳ��λ�����ں˻�����0������1����

    // �����Ե�ַ��Χ�ڣ����Ƿ���������Ϣ���ں˷�Χ�ڴ汻д����������� (address�C��ǰ

    // ���̴�����ʼ��ַ)����һ�����̵ij��ȣ�64MB������ʾaddress��ָ�����Ե�ַ��������

    // �쳣�Ľ������Ե�ַ�ռ䷶Χ�ڣ����ڷ���������Ϣ���˳���

389         if (address < TASK_SIZE)

390                 printk("\n\rBAD!! KERNEL PAGE MISSING\n\r");

391         if (address - current->start_code > TASK_SIZE) {

392                 printk("Bad things happen: nonexistent page error in do_no_page\n\r");

393                 do_exit(SIGSEGV);

394         }

    // Ȼ�����ָ�������Ե�ַaddress������Ӧ�Ķ���ҳ����ָ�룬�����ݸ�ҳ���������ж�

    // address����ҳ���Ƿ��ڽ����豸�С����������ҳ�沢�˳�������������ȡָ�����Ե�ַ

    // address��Ӧ��Ŀ¼�����ݡ������Ӧ�Ķ���ҳ�����ڣ���ȡ����Ŀ¼���ж���ҳ���ĵ�ַ��

    // ����ҳ����ƫ��ֵ���õ����Ե�ַaddress��ҳ���Ӧ��ҳ�����ָ�룬�Ӷ����ҳ������

    // �ݡ���ҳ�������ݲ�Ϊ0����ҳ�������λP=0����˵����ҳ����ָ��������ҳ��Ӧ���ڽ�

    // ���豸�С����Ǵӽ����豸�е���ָ��ҳ����˳�������

395         page = *(unsigned long *) ((address >> 20) & 0xffc); // ȡĿ¼�����ݡ�

396         if (page & 1) {

397                 page &= 0xfffff000;                          // ����ҳ����ַ��

398                 page += (address >> 10) & 0xffc;             // ҳ����ָ�롣

399                 tmp = *(unsigned long *) page;               // ҳ�������ݡ�

400                 if (tmp && !(1 & tmp)) {

401                         swap_in((unsigned long *) page);     // �ӽ����豸��ҳ�档

402                         return;

403                 }

404         }

    // ����ȡ���Կռ���ָ����ַaddress��ҳ���ַ�������ָ�����Ե�ַ�ڽ��̿ռ��������

    // ���̻�ַ��ƫ�Ƴ���ֵtmp������Ӧ���߼���ַ���Ӷ��������ȱҳҳ����ִ���ļ�ӳ����

    // ���ڿ��ļ��еľ�����ʼ���ݿ�š�

405         address &= 0xfffff000;                           // address��ȱҳҳ���ַ��

406         tmp = address - current->start_code;             // ȱҳҳ���Ӧ�߼���ַ��

 

    // ���ȱҳ��Ӧ���߼���ַtmp���ڿ�ӳ���ļ��ڽ����߼��ռ��е���ʼλ�ã�˵��ȱ�ٵ�ҳ

    // ���ڿ�ӳ���ļ��С����Ǵӵ�ǰ�����������ݽṹ�п���ȡ�ÿ�ӳ���ļ���i�ڵ�library��

    // ���������ȱҳ�ڿ��ļ��е���ʼ���ݿ��block�����ȱҳ��Ӧ���߼���ַtmpС�ڽ���

    // ��ִ��ӳ���ļ����߼���ַ�ռ��ĩ��λ�ã���˵��ȱ�ٵ�ҳ���ڽ���ִ���ļ�ӳ���У���

    // �ǿ��Դӵ�ǰ�����������ݻ�����ȡ��ִ���ļ���i�ڵ��executable�����������ȱҳ

    // ��ִ���ļ�ӳ���е���ʼ���ݿ��block�����߼���ַtmp�Ȳ���ִ���ļ�ӳ��ĵ�ַ��Χ

    // �ڣ�Ҳ���ڿ��ļ��ռ䷶Χ�ڣ���˵��ȱҳ�ǽ��̷��ʶ�̬������ڴ�ҳ���������£����

    // û�ж�Ӧi�ڵ�����ݿ�ţ����ÿգ���

    // ��Ϊ���豸�ϴ�ŵ�ִ���ļ�ӳ���1�������dz���ͷ�ṹ������ڶ�ȡ���ļ�ʱ��Ҫ����

    // ��1�����ݡ�������Ҫ���ȼ���ȱҳ���ڵ����ݿ�š���Ϊÿ�����ݳ���ΪBLOCK_SIZE =

    // 1KB�����һҳ�ڴ�ɴ��4�����ݿ顣�����߼���ַtmp�������ݿ��С�ټ�1���ɵó�

    // ȱ�ٵ�ҳ����ִ��ӳ���ļ��е���ʼ���block��

407         if (tmp >= LIBRARY_OFFSET ) {

408                 inode = current->library;          // ���ļ�i�ڵ��ȱҳ��ʼ��š�

409                 block = 1 + (tmp-LIBRARY_OFFSET) / BLOCK_SIZE;

410         } else if (tmp < current->end_data) {

411                 inode = current->executable;       // ִ���ļ�i�ڵ��ȱҳ��ʼ��š�

412                 block = 1 + tmp / BLOCK_SIZE;

413         } else {

414                 inode = NULL;                      // �Ƕ�̬��������ݻ�ջ�ڴ�ҳ�档

415                 block = 0;

416         }

    // ���ǽ��̷����䶯̬�����ҳ���Ϊ�˴��ջ��Ϣ�������ȱҳ�쳣����ֱ������һҳ��

    // ���ڴ�ҳ�沢ӳ�䵽���Ե�ַaddress�����ɡ�����˵����ȱҳ���ڽ���ִ���ļ������

    // ����Χ�ڣ����Ǿͳ��Թ���ҳ����������ɹ����˳��������ɹ���ֻ������һҳ�����ڴ�

    // ҳ��page��Ȼ����豸�϶�ȡִ���ļ��е���Ӧҳ�沢���ã�ӳ�䣩������ҳ���߼���ַ

    // tmp����

417         if (!inode) {                              // �Ƕ�̬����������ڴ�ҳ�档

418                 get_empty_page(address);

419                 return;

420         }

421         if (share_page(inode,tmp))                 // �����߼���ַtmp��ҳ��Ĺ�����

422                 return;

423         if (!(page = get_free_page()))             // ����һҳ�����ڴ档

424                 oom();

425 /* remember that 1 block is used for header */

    /* ��ס��������ͷҪʹ��1�����ݿ� */

    // ���������ź�ִ���ļ���i�ڵ㣬���ǾͿ��Դ�ӳ��λͼ���ҵ���Ӧ���豸�ж�Ӧ���豸

    // �߼���ţ�������nr[]�����У�������bread_page()���ɰ���4���߼�����뵽����ҳ��

    // page�С�

426         for (i=0 ; i<4 ; block++,i++)

427                 nr[i] = bmap(inode,block);

428         bread_page(page,inode->i_dev,nr);

 

    // �ڶ��豸�߼������ʱ�����ܻ��������һ�����������ִ���ļ��еĶ�ȡҳ��λ�ÿ�����

    // �ļ�β����1��ҳ��ij��ȡ���˾Ϳ��ܶ���һЩ���õ���Ϣ������IJ������ǰ��ⲿ�ֳ�

    // ��ִ���ļ�end_data�Ժ�IJ��ֽ������㴦������Ȼ������ҳ����ĩ�˳���1ҳ��˵����

    // �Ǵ�ִ���ļ�ӳ���ж�ȡ��ҳ�棬���Ǵӿ��ļ��ж�ȡ�ģ���˲���ִ�����������

429         i = tmp + 4096 - current->end_data;          // �������ֽڳ���ֵ��

430         if (i>4095)                                  // ��ĩ�˳���1ҳ�������㡣

431                 i = 0;

432         tmp = page + 4096;                           // tmpָ��ҳ��ĩ�ˡ�

433         while (i-- > 0) {                            // ҳ��ĩ��i�ֽ����㡣

434                 tmp--;

435                 *(char *)tmp = 0;

436         }

    // ��������ȱҳ�쳣��һҳ����ҳ��ӳ�䵽ָ�����Ե�ַaddress�����������ɹ��ͷ��ء�

    // ������ͷ��ڴ�ҳ����ʾ�ڴ治����

437         if (put_page(page,address))

438                 return;

439         free_page(page);

440         oom();

441 }

442

    //// �����ڴ������ʼ����

    // �ú�����1MB�����ڴ�������ҳ��Ϊ��λ���й���ǰ�ij�ʼ�����ù�����һ��ҳ�泤��Ϊ

    // 4KB�ֽڡ��ú����� 1MB�������������ڴ滮�ֳ�һ����ҳ�棬��ʹ��һ��ҳ��ӳ���ֽ�

    // ����mem_map[] ������������Щҳ�档���ھ���16MB�ڴ������Ļ����������鹲��3840

    // �� ((16MB - 1MB)/4KB)�����ɹ���3840������ҳ�档ÿ��һ�������ڴ�ҳ�汻ռ��ʱ��

    // �� mem_map[]�ж�Ӧ�ĵ��ֽ�ֵ��1�����ͷ�һ������ҳ�棬�ͰѶ�Ӧ�ֽ�ֵ��1�� ����

    // ��ֵΪ 0�����ʾ��Ӧҳ����У� ���ֽ�ֵ���ڻ����1�����ʾ��Ӧҳ�汻ռ�û򱻲�

    // ͬ������ռ�á�

    // �ڸð汾�� Linux�ں��У�����ܹ��� 16MB�������ڴ棬����16MB���ڴ潫���ò��á�

    // ���ھ���16MB�ڴ��PC��ϵͳ����û������������ RAMDISK������� start_memͨ��

    // ��4MB��end_mem��16MB����˴�ʱ���ڴ�����Χ��4MB��16MB������3072������ҳ���

    // �����䡣����Χ0 - 1MB�ڴ�ռ������ں�ϵͳ����ʵ�ں�ֻʹ��0 ��640Kb��ʣ�µIJ�

    // �ֱ����ָ��ٻ�����豸�ڴ�ռ�ã���

    // ����start_mem�ǿ�����ҳ���������ڴ�����ʼ��ַ����ȥ��RAMDISK��ռ�ڴ�ռ䣩��

    // end_mem��ʵ�������ڴ�����ַ������ַ��Χstart_mem��end_mem�����ڴ�����

443 void mem_init(long start_mem, long end_mem)

444 {

445         int i;

446

    // ���Ƚ�1MB��16MB��Χ�������ڴ�ҳ���Ӧ���ڴ�ӳ���ֽ���������Ϊ��ռ��״̬������

    // ���ֽ�ֵȫ�����ó�USED��100����PAGING_PAGES������Ϊ(PAGING_MEMORY>>12)����1MB

    // �������������ڴ��ҳ����ڴ�ҳ����(15MB/4KB = 3840)��

447         HIGH_MEMORY = end_mem;                     // �����ڴ���߶ˣ�16MB����

448         for (i=0 ; i<PAGING_PAGES ; i++)

449                 mem_map[i] = USED;

    // Ȼ��������ڴ�����ʼ�ڴ� start_mem ��ҳ���Ӧ�ڴ�ӳ���ֽ����������i�����ڴ���

    // ҳ��������ʱ mem_map[] ����ĵ�i������Ӧ���ڴ����е�1��ҳ�档������ڴ�����

    // ҳ���Ӧ�����������㣨��ʾ���У������ھ���16MB�����ڴ��ϵͳ��mem_map[] �ж�Ӧ

    // 4Mb--16Mb���ڴ���������㡣

450         i = MAP_NR(start_mem);                     // ���ڴ�����ʼλ�ô�ҳ��š�

451         end_mem -= start_mem;

452         end_mem >>= 12;                            // ���ڴ����е���ҳ������

453         while (end_mem-->0)

454                 mem_map[i++]=0;                    // ���ڴ���ҳ���Ӧ�ֽ�ֵ���㡣

455 }

456

    // ��ʾϵͳ�ڴ���Ϣ��

    // �����ڴ�ӳ���ֽ����� mem_map[] �е���Ϣ�Լ�ҳĿ¼��ҳ������ͳ��ϵͳ��ʹ�õ��ڴ�ҳ

    // ���������ڴ������������ڴ�ҳ�������ú����� chr_drv/keyboard.S�����186�б����á�

    // �������¡�Shift + Scroll Lock����ϼ�ʱ����ʾϵͳ�ڴ�ͳ����Ϣ��

457 void show_mem(void)

458 {

459         int i,j,k,free=0,total=0;

460         int shared=0;

461         unsigned long * pg_tbl;

462

    // �����ڴ�ӳ���ֽ�����mem_map[]��ͳ��ϵͳ���ڴ���ҳ������total���Լ����п���ҳ��

    // ��free�ͱ�������ҳ����shared������Щ��Ϣ��ʾ��

463         printk("Mem-info:\n\r");

464         for(i=0 ; i<PAGING_PAGES ; i++) {

465                 if (mem_map[i] == USED)              // 1MB�����ڴ�ϵͳռ�õ�ҳ�档

466                         continue;

467                 total++;

468                 if (!mem_map[i])

469                         free++;                      // ���ڴ�������ҳ��ͳ�ơ�

470                 else

471                         shared += mem_map[i]-1;      // ������ҳ�������ֽ�ֵ>1����

472         }

473         printk("%d free pages of %d\n\r",free,total);

474         printk("%d pages shared\n\r",shared);

 

    // ͳ�ƴ�������ҳ�����߼�ҳ������ҳĿ¼��ǰ4��ں˴���ʹ�ã�����Ϊͳ�Ʒ�Χ�����

    // ɨ�账����ҳĿ¼��ӵ�5�ʼ��������ѭ����������ҳĿ¼���ǰ4���������Ӧ

    // �Ķ���ҳ�����ڣ���ô��ͳ�ƶ���ҳ������ռ�õ��ڴ�ҳ�棨484�У���Ȼ��Ը�ҳ������

    // ��ҳ�����Ӧҳ���������ͳ�ơ�

475         k = 0;                                           // һ������ռ��ҳ��ͳ��ֵ��

476         for(i=4 ; i<1024 ;) {

477                 if (1&pg_dir[i]) {

    // �����ҳĿ¼���Ӧ����ҳ����ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����Ŀ¼��

    // �����⡣������ʾ��Ŀ¼����Ϣ������������һ��Ŀ¼���

478                         if (pg_dir[i]>HIGH_MEMORY) {         // Ŀ¼�����ݲ�������

479                                 printk("page directory[%d]: %08X\n\r",

480                                         i,pg_dir[i]);

481                                 continue;                // continue֮ǰ�����i++��

482                         }

    // ���ҳĿ¼���Ӧ����ҳ���ġ���ַ������LOW_MEM����1MB�������һ������ռ�õ�����

    // �ڴ�ҳͳ��ֵk��1����ϵͳռ�õ����������ڴ�ҳͳ��ֵfree��1��Ȼ��ȡ��Ӧҳ����ַ

    // pg_tbl�����Ը�ҳ��������ҳ�������ͳ�ơ������ǰҳ������ָ����ҳ����ڲ��Ҹ�����

    // ҳ�桰��ַ������LOW_MEM����ô�ͽ�ҳ�����Ӧҳ������ͳ��ֵ��

483                         if (pg_dir[i]>LOW_MEM)

484                                 free++,k++;              // ͳ��ҳ��ռ��ҳ�档

485                         pg_tbl=(unsigned long *) (0xfffff000 & pg_dir[i]);

486                         for(j=0 ; j<1024 ; j++)

487                                 if ((pg_tbl[j]&1) && pg_tbl[j]>LOW_MEM)

    // ����������ҳ���ַ���ڻ�����������ڴ��ַHIGH_MEMORY����˵����ҳ�������������⣬

    // ������ʾ��ҳ�������ݡ�����ҳ�����Ӧҳ������ͳ��ֵ����

488                                         if (pg_tbl[j]>HIGH_MEMORY)

489                                                 printk("page_dir[%d][%d]: %08X\n\r",

490                                                         i,j, pg_tbl[j]);

491                                         else

492                                                 k++,free++;  // ͳ��ҳ�����Ӧҳ�档

493                 }

    // ��ÿ���������Կռ䳤����64MB������һ������ռ��16��Ŀ¼��������ÿͳ����16��

    // Ŀ¼��Ͱѽ��̵�����ṹռ�õ�ҳ��ͳ�ƽ���������ʱk=0���ʾ��ǰ��16��ҳĿ¼����

    // Ӧ�Ľ�����ϵͳ�в����ڣ�û�д��������Ѿ���ֹ���� ����ʾ�˶�Ӧ���̺ź���ռ�õ�����

    // �ڴ�ҳͳ��ֵk�󣬽�k���㣬������ͳ����һ������ռ�õ��ڴ�ҳ������

494                 i++;

495                 if (!(i&15) && k) {                // k !=0 ��ʾ��Ӧ���̴��ڡ�

496                         k++,free++;     /* one page/process for task_struct */

497                         printk("Process %d: %d pages\n\r",(i>>4)-1,k);

498                         k = 0;

499                 }

500         }

    // �����ʾϵͳ������ʹ�õ��ڴ�ҳ������ڴ������ܵ��ڴ�ҳ������

501         printk("Memory found: %d (%d)\n\r",free-shared,total);

502 }

503